smallworld-re 1.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 (166) hide show
  1. smallworld/__init__.py +35 -0
  2. smallworld/analyses/__init__.py +14 -0
  3. smallworld/analyses/analysis.py +88 -0
  4. smallworld/analyses/code_coverage.py +31 -0
  5. smallworld/analyses/colorizer.py +682 -0
  6. smallworld/analyses/colorizer_summary.py +100 -0
  7. smallworld/analyses/field_detection/__init__.py +14 -0
  8. smallworld/analyses/field_detection/field_analysis.py +536 -0
  9. smallworld/analyses/field_detection/guards.py +26 -0
  10. smallworld/analyses/field_detection/hints.py +133 -0
  11. smallworld/analyses/field_detection/malloc.py +211 -0
  12. smallworld/analyses/forced_exec/__init__.py +3 -0
  13. smallworld/analyses/forced_exec/forced_exec.py +87 -0
  14. smallworld/analyses/underlays/__init__.py +4 -0
  15. smallworld/analyses/underlays/basic.py +13 -0
  16. smallworld/analyses/underlays/underlay.py +31 -0
  17. smallworld/analyses/unstable/__init__.py +4 -0
  18. smallworld/analyses/unstable/angr/__init__.py +0 -0
  19. smallworld/analyses/unstable/angr/base.py +12 -0
  20. smallworld/analyses/unstable/angr/divergence.py +274 -0
  21. smallworld/analyses/unstable/angr/model.py +383 -0
  22. smallworld/analyses/unstable/angr/nwbt.py +63 -0
  23. smallworld/analyses/unstable/angr/typedefs.py +170 -0
  24. smallworld/analyses/unstable/angr/utils.py +25 -0
  25. smallworld/analyses/unstable/angr/visitor.py +315 -0
  26. smallworld/analyses/unstable/angr_nwbt.py +106 -0
  27. smallworld/analyses/unstable/code_coverage.py +54 -0
  28. smallworld/analyses/unstable/code_reachable.py +44 -0
  29. smallworld/analyses/unstable/control_flow_tracer.py +71 -0
  30. smallworld/analyses/unstable/pointer_finder.py +90 -0
  31. smallworld/arch/__init__.py +0 -0
  32. smallworld/arch/aarch64_arch.py +286 -0
  33. smallworld/arch/amd64_arch.py +86 -0
  34. smallworld/arch/i386_arch.py +44 -0
  35. smallworld/emulators/__init__.py +14 -0
  36. smallworld/emulators/angr/__init__.py +7 -0
  37. smallworld/emulators/angr/angr.py +1652 -0
  38. smallworld/emulators/angr/default.py +15 -0
  39. smallworld/emulators/angr/exceptions.py +7 -0
  40. smallworld/emulators/angr/exploration/__init__.py +9 -0
  41. smallworld/emulators/angr/exploration/bounds.py +27 -0
  42. smallworld/emulators/angr/exploration/default.py +17 -0
  43. smallworld/emulators/angr/exploration/terminate.py +22 -0
  44. smallworld/emulators/angr/factory.py +55 -0
  45. smallworld/emulators/angr/machdefs/__init__.py +35 -0
  46. smallworld/emulators/angr/machdefs/aarch64.py +292 -0
  47. smallworld/emulators/angr/machdefs/amd64.py +192 -0
  48. smallworld/emulators/angr/machdefs/arm.py +387 -0
  49. smallworld/emulators/angr/machdefs/i386.py +221 -0
  50. smallworld/emulators/angr/machdefs/machdef.py +138 -0
  51. smallworld/emulators/angr/machdefs/mips.py +184 -0
  52. smallworld/emulators/angr/machdefs/mips64.py +189 -0
  53. smallworld/emulators/angr/machdefs/ppc.py +101 -0
  54. smallworld/emulators/angr/machdefs/riscv.py +261 -0
  55. smallworld/emulators/angr/machdefs/xtensa.py +255 -0
  56. smallworld/emulators/angr/memory/__init__.py +7 -0
  57. smallworld/emulators/angr/memory/default.py +10 -0
  58. smallworld/emulators/angr/memory/fixups.py +43 -0
  59. smallworld/emulators/angr/memory/memtrack.py +105 -0
  60. smallworld/emulators/angr/scratch.py +43 -0
  61. smallworld/emulators/angr/simos.py +53 -0
  62. smallworld/emulators/angr/utils.py +70 -0
  63. smallworld/emulators/emulator.py +1013 -0
  64. smallworld/emulators/hookable.py +252 -0
  65. smallworld/emulators/panda/__init__.py +5 -0
  66. smallworld/emulators/panda/machdefs/__init__.py +28 -0
  67. smallworld/emulators/panda/machdefs/aarch64.py +93 -0
  68. smallworld/emulators/panda/machdefs/amd64.py +71 -0
  69. smallworld/emulators/panda/machdefs/arm.py +89 -0
  70. smallworld/emulators/panda/machdefs/i386.py +36 -0
  71. smallworld/emulators/panda/machdefs/machdef.py +86 -0
  72. smallworld/emulators/panda/machdefs/mips.py +94 -0
  73. smallworld/emulators/panda/machdefs/mips64.py +91 -0
  74. smallworld/emulators/panda/machdefs/ppc.py +79 -0
  75. smallworld/emulators/panda/panda.py +575 -0
  76. smallworld/emulators/unicorn/__init__.py +13 -0
  77. smallworld/emulators/unicorn/machdefs/__init__.py +28 -0
  78. smallworld/emulators/unicorn/machdefs/aarch64.py +310 -0
  79. smallworld/emulators/unicorn/machdefs/amd64.py +326 -0
  80. smallworld/emulators/unicorn/machdefs/arm.py +321 -0
  81. smallworld/emulators/unicorn/machdefs/i386.py +137 -0
  82. smallworld/emulators/unicorn/machdefs/machdef.py +117 -0
  83. smallworld/emulators/unicorn/machdefs/mips.py +202 -0
  84. smallworld/emulators/unicorn/unicorn.py +684 -0
  85. smallworld/exceptions/__init__.py +5 -0
  86. smallworld/exceptions/exceptions.py +85 -0
  87. smallworld/exceptions/unstable/__init__.py +1 -0
  88. smallworld/exceptions/unstable/exceptions.py +25 -0
  89. smallworld/extern/__init__.py +4 -0
  90. smallworld/extern/ctypes.py +94 -0
  91. smallworld/extern/unstable/__init__.py +1 -0
  92. smallworld/extern/unstable/ghidra.py +129 -0
  93. smallworld/helpers.py +107 -0
  94. smallworld/hinting/__init__.py +8 -0
  95. smallworld/hinting/hinting.py +214 -0
  96. smallworld/hinting/hints.py +427 -0
  97. smallworld/hinting/unstable/__init__.py +2 -0
  98. smallworld/hinting/utils.py +19 -0
  99. smallworld/instructions/__init__.py +18 -0
  100. smallworld/instructions/aarch64.py +20 -0
  101. smallworld/instructions/arm.py +18 -0
  102. smallworld/instructions/bsid.py +67 -0
  103. smallworld/instructions/instructions.py +258 -0
  104. smallworld/instructions/mips.py +21 -0
  105. smallworld/instructions/x86.py +100 -0
  106. smallworld/logging.py +90 -0
  107. smallworld/platforms.py +95 -0
  108. smallworld/py.typed +0 -0
  109. smallworld/state/__init__.py +6 -0
  110. smallworld/state/cpus/__init__.py +32 -0
  111. smallworld/state/cpus/aarch64.py +563 -0
  112. smallworld/state/cpus/amd64.py +676 -0
  113. smallworld/state/cpus/arm.py +630 -0
  114. smallworld/state/cpus/cpu.py +71 -0
  115. smallworld/state/cpus/i386.py +239 -0
  116. smallworld/state/cpus/mips.py +374 -0
  117. smallworld/state/cpus/mips64.py +372 -0
  118. smallworld/state/cpus/powerpc.py +229 -0
  119. smallworld/state/cpus/riscv.py +357 -0
  120. smallworld/state/cpus/xtensa.py +80 -0
  121. smallworld/state/memory/__init__.py +7 -0
  122. smallworld/state/memory/code.py +70 -0
  123. smallworld/state/memory/elf/__init__.py +3 -0
  124. smallworld/state/memory/elf/elf.py +564 -0
  125. smallworld/state/memory/elf/rela/__init__.py +32 -0
  126. smallworld/state/memory/elf/rela/aarch64.py +27 -0
  127. smallworld/state/memory/elf/rela/amd64.py +32 -0
  128. smallworld/state/memory/elf/rela/arm.py +51 -0
  129. smallworld/state/memory/elf/rela/i386.py +32 -0
  130. smallworld/state/memory/elf/rela/mips.py +45 -0
  131. smallworld/state/memory/elf/rela/ppc.py +45 -0
  132. smallworld/state/memory/elf/rela/rela.py +63 -0
  133. smallworld/state/memory/elf/rela/riscv64.py +27 -0
  134. smallworld/state/memory/elf/rela/xtensa.py +15 -0
  135. smallworld/state/memory/elf/structs.py +55 -0
  136. smallworld/state/memory/heap.py +85 -0
  137. smallworld/state/memory/memory.py +181 -0
  138. smallworld/state/memory/stack/__init__.py +31 -0
  139. smallworld/state/memory/stack/aarch64.py +22 -0
  140. smallworld/state/memory/stack/amd64.py +42 -0
  141. smallworld/state/memory/stack/arm.py +66 -0
  142. smallworld/state/memory/stack/i386.py +22 -0
  143. smallworld/state/memory/stack/mips.py +34 -0
  144. smallworld/state/memory/stack/mips64.py +34 -0
  145. smallworld/state/memory/stack/ppc.py +34 -0
  146. smallworld/state/memory/stack/riscv.py +22 -0
  147. smallworld/state/memory/stack/stack.py +127 -0
  148. smallworld/state/memory/stack/xtensa.py +34 -0
  149. smallworld/state/models/__init__.py +6 -0
  150. smallworld/state/models/mmio.py +186 -0
  151. smallworld/state/models/model.py +163 -0
  152. smallworld/state/models/posix.py +455 -0
  153. smallworld/state/models/x86/__init__.py +2 -0
  154. smallworld/state/models/x86/microsoftcdecl.py +35 -0
  155. smallworld/state/models/x86/systemv.py +240 -0
  156. smallworld/state/state.py +962 -0
  157. smallworld/state/unstable/__init__.py +0 -0
  158. smallworld/state/unstable/elf.py +393 -0
  159. smallworld/state/x86_registers.py +30 -0
  160. smallworld/utils.py +935 -0
  161. smallworld_re-1.0.0.dist-info/LICENSE.txt +21 -0
  162. smallworld_re-1.0.0.dist-info/METADATA +189 -0
  163. smallworld_re-1.0.0.dist-info/RECORD +166 -0
  164. smallworld_re-1.0.0.dist-info/WHEEL +5 -0
  165. smallworld_re-1.0.0.dist-info/entry_points.txt +2 -0
  166. smallworld_re-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,258 @@
1
+ import abc
2
+ import logging
3
+ import typing
4
+
5
+ import capstone
6
+
7
+ from .. import emulators, utils
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class Operand(metaclass=abc.ABCMeta):
13
+ """An operand from an instruction."""
14
+
15
+ @abc.abstractmethod
16
+ def key(self, emulator: emulators.Emulator):
17
+ """Provide a unique key for this reference.
18
+
19
+ Arguments:
20
+ emulator: An emulator from which to fetch a value.
21
+
22
+ Returns:
23
+ A key value used to reference this operand.
24
+ """
25
+
26
+ pass
27
+
28
+ @abc.abstractmethod
29
+ def concretize(
30
+ self, emulator: emulators.Emulator
31
+ ) -> typing.Optional[typing.Union[int, bytes]]:
32
+ """Compute a concrete value for this operand, using an emulator.
33
+
34
+ Arguments:
35
+ emulator: An emulator from which to fetch a value.
36
+
37
+ Returns:
38
+ The concrete value of this operand.
39
+ """
40
+
41
+ pass
42
+
43
+
44
+ class RegisterOperand(Operand):
45
+ """An operand from an instruction that is simply a register."""
46
+
47
+ def __init__(self, name: str):
48
+ self.name = name
49
+
50
+ def key(self, emulator: emulators.Emulator):
51
+ return self.name
52
+
53
+ def __eq__(self, other) -> bool:
54
+ return hash(self) == hash(other)
55
+
56
+ def __hash__(self) -> int:
57
+ return hash(self.__repr__())
58
+
59
+ def concretize(self, emulator: emulators.Emulator) -> int:
60
+ return emulator.read_register(self.name)
61
+
62
+ def __repr__(self) -> str:
63
+ return f"{self.__class__.__name__}({self.name})"
64
+
65
+
66
+ class MemoryReferenceOperand(Operand):
67
+ """An operand from an instruction which reads or writes memory."""
68
+
69
+ def __init__(self, size: int = 4):
70
+ self.size = size
71
+
72
+ @abc.abstractmethod
73
+ def address(self, emulator: emulators.Emulator) -> int:
74
+ """Compute a concrete value for this operand.
75
+
76
+ Arguments:
77
+ emulator: An emulator from which to fetch a value.
78
+
79
+ Returns:
80
+ The concrete value of this operand.
81
+ """
82
+
83
+ def key(self, emulator: emulators.Emulator) -> int:
84
+ return self.address(emulator)
85
+
86
+ def __eq__(self, other):
87
+ return self.__repr__() == other.__repr__()
88
+
89
+ def __hash__(self):
90
+ return hash(self.__repr__())
91
+
92
+ def concretize(self, emulator: emulators.Emulator) -> typing.Optional[bytes]:
93
+ return emulator.read_memory(self.address(emulator), self.size)
94
+
95
+
96
+ class Instruction(metaclass=abc.ABCMeta):
97
+ """An instruction storage and semantic metadata class."""
98
+
99
+ def __init__(
100
+ self,
101
+ instruction: bytes,
102
+ address: int,
103
+ _instruction: typing.Optional[capstone.CsInsn] = None,
104
+ ):
105
+ self.instruction = instruction
106
+ self.address = address
107
+
108
+ if _instruction is None:
109
+ md = capstone.Cs(self.cs_arch, self.cs_mode)
110
+ md.detail = True
111
+
112
+ _instruction = md.disasm(instruction, address).__next__()
113
+
114
+ self._instruction = _instruction
115
+ self.disasm = f"{self._instruction.address:x} {self._instruction.mnemonic} {self._instruction.op_str}"
116
+
117
+ @property
118
+ @abc.abstractmethod
119
+ def angr_arch(self) -> str:
120
+ """angr architecture ID"""
121
+ return ""
122
+
123
+ @property
124
+ @abc.abstractmethod
125
+ def cs_arch(self) -> int:
126
+ """Capstone architecture ID"""
127
+ return 0
128
+
129
+ @property
130
+ @abc.abstractmethod
131
+ def cs_mode(self) -> int:
132
+ """Capstone mode ID"""
133
+ return 0
134
+
135
+ @classmethod
136
+ def from_capstone(cls, instruction: capstone.CsInsn):
137
+ """Construct from an existing Capstone instruction.
138
+
139
+ Arguments:
140
+ instruction: An existing Capstone instruction.
141
+ """
142
+ try:
143
+ return utils.find_subclass(
144
+ cls,
145
+ check=lambda x: x.cs_arch == instruction._cs.arch
146
+ and x.cs_mode == instruction._cs.mode,
147
+ instruction=instruction.bytes,
148
+ address=instruction.address,
149
+ _instruction=instruction,
150
+ )
151
+ except ValueError:
152
+ raise ValueError(
153
+ f"No instruction format for {instruction._cs.arch}:{instruction._cs.mode}"
154
+ )
155
+
156
+ @classmethod
157
+ def from_angr(cls, instruction, block, arch: str):
158
+ """Construct from an angr disassembler instruction.
159
+
160
+ Arguments:
161
+ instruction: An existing angr disassembler instruction
162
+ arch: angr architecture string
163
+ """
164
+ # angr's instructions don't include raw bytes.
165
+ off = instruction.address - block.addr
166
+ raw = block.bytes[off : off + instruction.size]
167
+ try:
168
+ return utils.find_subclass(
169
+ cls,
170
+ check=lambda x: x.angr_arch == arch,
171
+ instruction=raw,
172
+ address=instruction.address,
173
+ )
174
+ except ValueError:
175
+ raise ValueError(f"No instruction format for {arch}")
176
+
177
+ @classmethod
178
+ def from_bytes(cls, raw: bytes, address: int, arch: str, mode: str):
179
+ """Construct from a byte string."""
180
+ try:
181
+ return utils.find_subclass(
182
+ cls,
183
+ check=lambda x: x.arch == arch and x.mode == mode,
184
+ instruction=raw,
185
+ address=address,
186
+ )
187
+ except ValueError:
188
+ raise ValueError(f"No instruction format for {arch}:{mode}")
189
+
190
+ @abc.abstractmethod
191
+ def _memory_reference(self, operand) -> MemoryReferenceOperand:
192
+ pass
193
+
194
+ @property
195
+ def reads(self) -> typing.Set[Operand]:
196
+ """Registers and memory references read by this instruction.
197
+
198
+ This is a list of string register names and dictionary memory reference
199
+ specifications (i.e., in the form `base + scale * index + offset`).
200
+ """
201
+
202
+ read: typing.Set[Operand] = set()
203
+
204
+ for operand in self._instruction.operands:
205
+ if operand.type == capstone.CS_OP_MEM and (
206
+ not hasattr(operand, "access") or operand.access & capstone.CS_AC_READ
207
+ ):
208
+ read.add(self._memory_reference(operand))
209
+ elif operand.type == capstone.CS_OP_REG and (
210
+ not hasattr(operand, "access") or operand.access & capstone.CS_AC_READ
211
+ ):
212
+ read.add(RegisterOperand(self._instruction.reg_name(operand.reg)))
213
+
214
+ return read
215
+
216
+ @property
217
+ def writes(self) -> typing.Set[Operand]:
218
+ """Registers and memory references written by this instruction.
219
+
220
+ Same format as `reads`.
221
+ """
222
+
223
+ write: typing.Set[Operand] = set()
224
+
225
+ for operand in self._instruction.operands:
226
+ if operand.type == capstone.CS_OP_MEM and (
227
+ not hasattr(operand, "access") or operand.access & capstone.CS_AC_WRITE
228
+ ):
229
+ write.add(self._memory_reference(operand))
230
+ elif operand.type == capstone.CS_OP_REG and (
231
+ not hasattr(operand, "access") or operand.access & capstone.CS_AC_WRITE
232
+ ):
233
+ write.add(RegisterOperand(self._instruction.reg_name(operand.reg)))
234
+
235
+ return write
236
+
237
+ # def to_json(self) -> dict:
238
+ # return {
239
+ # "instruction": base64.b64encode(self.instruction).decode(),
240
+ # "disasm": self.disasm,
241
+ # "address": self.address,
242
+ # "arch": self.arch,
243
+ # "mode": self.mode,
244
+ # }
245
+
246
+ # @classmethod
247
+ # def from_json(cls, dict):
248
+ # if "instruction" not in dict:
249
+ # raise ValueError(f"malformed {cls.__name__}: {dict!r}")
250
+
251
+ # dict["instruction"] = base64.b64decode(dict["instruction"])
252
+
253
+ # return cls(**dict)
254
+
255
+ def __repr__(self) -> str:
256
+ string = f"{self._instruction.mnemonic} {self._instruction.op_str}".strip()
257
+
258
+ return f"{self.__class__.__name__}(0x{self.address:x}: {string})"
@@ -0,0 +1,21 @@
1
+ import capstone
2
+
3
+ from .bsid import BSIDMemoryReferenceOperand
4
+ from .instructions import Instruction, MemoryReferenceOperand
5
+
6
+
7
+ class MIPSInstruction(Instruction):
8
+ angr_arch = "MIPS"
9
+ cs_arch = capstone.CS_ARCH_MIPS
10
+ cs_mode = capstone.CS_MODE_MIPS32 | capstone.CS_MODE_BIG_ENDIAN
11
+
12
+ def _memory_reference(self, operand) -> MemoryReferenceOperand:
13
+ return BSIDMemoryReferenceOperand(
14
+ base=self._instruction.reg_name(operand.value.mem.base),
15
+ offset=operand.value.mem.disp,
16
+ size=4,
17
+ )
18
+
19
+
20
+ class MIPSELInstruction(MIPSInstruction):
21
+ cs_mode = capstone.CS_MODE_MIPS32
@@ -0,0 +1,100 @@
1
+ import typing
2
+
3
+ import capstone
4
+
5
+ from .bsid import BSIDMemoryReferenceOperand
6
+ from .instructions import Instruction, MemoryReferenceOperand, Operand, RegisterOperand
7
+
8
+
9
+ class x86Instruction(Instruction):
10
+ word_size = 4
11
+ angr_arch = "X86"
12
+ cs_arch = capstone.CS_ARCH_X86
13
+ cs_mode = capstone.CS_MODE_32
14
+ sp = "esp"
15
+
16
+ def _memory_reference(self, base, index, scale, offset, size):
17
+ return BSIDMemoryReferenceOperand(
18
+ base=base, index=index, scale=scale, offset=offset, size=size
19
+ )
20
+
21
+ # operand is a capstone operand
22
+ def _memory_reference_operand(self, operand) -> MemoryReferenceOperand:
23
+ return self._memory_reference(
24
+ self._instruction.reg_name(operand.value.mem.base),
25
+ self._instruction.reg_name(operand.value.mem.index),
26
+ operand.value.mem.scale,
27
+ operand.value.mem.disp,
28
+ operand.size,
29
+ )
30
+
31
+ @property
32
+ def reads(self) -> typing.Set[Operand]:
33
+ """Registers and memory references read by this instruction.
34
+
35
+ This is a list of string register names and dictionary memory reference
36
+ specifications (i.e., in the form `base + scale * index + offset`).
37
+ """
38
+
39
+ reg_reads, _ = self._instruction.regs_access()
40
+ the_reads: typing.Set[Operand] = set(
41
+ [RegisterOperand(self._instruction.reg_name(r)) for r in reg_reads]
42
+ )
43
+
44
+ for operand in self._instruction.operands:
45
+ if operand.access & capstone.CS_AC_READ:
46
+ if operand.type == capstone.x86.X86_OP_MEM:
47
+ if not self._instruction.mnemonic == "lea":
48
+ # add the actual memory read
49
+ the_reads.add(self._memory_reference_operand(operand))
50
+ # add reads for parts of the operand
51
+ base_name = self._instruction.reg_name(operand.mem.base)
52
+ index_name = self._instruction.reg_name(operand.mem.index)
53
+ if base_name:
54
+ the_reads.add(RegisterOperand(base_name))
55
+ if index_name:
56
+ the_reads.add(RegisterOperand(index_name))
57
+ elif operand.type == capstone.x86.X86_OP_REG:
58
+ # these are already in the list bc of regs_access above
59
+ pass
60
+ else:
61
+ # shouldn't happen
62
+ assert 1 == 0
63
+ if self._instruction.mnemonic == "pop":
64
+ the_reads.add(self._memory_reference(self.sp, None, 1, 0, self.word_size))
65
+
66
+ return the_reads
67
+
68
+ @property
69
+ def writes(self) -> typing.Set[Operand]:
70
+ """Registers and memory references written by this instruction.
71
+
72
+ Same format as `reads`.
73
+ """
74
+ _, reg_writes = self._instruction.regs_access()
75
+ the_writes: typing.Set[Operand] = set(
76
+ [RegisterOperand(self._instruction.reg_name(r)) for r in reg_writes]
77
+ )
78
+ for operand in self._instruction.operands:
79
+ if operand.access & capstone.CS_AC_WRITE:
80
+ # please dont change this to CS_OP_MEM bc that doesnt work?
81
+ if operand.type == capstone.x86.X86_OP_MEM:
82
+ assert not (self._instruction.mnemonic == "lea")
83
+ the_writes.add(self._memory_reference_operand(operand))
84
+ elif operand.type == capstone.x86.X86_OP_REG:
85
+ # operands doesn't contain implicit registers.
86
+ # we get all registers from regs_write
87
+ pass
88
+ else:
89
+ assert 1 == 0
90
+ if self._instruction.mnemonic == "push":
91
+ the_writes.add(self._memory_reference(self.sp, None, 1, 0, self.word_size))
92
+
93
+ return the_writes
94
+
95
+
96
+ class AMD64Instruction(x86Instruction):
97
+ angr_arch = "AMD64"
98
+ cs_mode = capstone.CS_MODE_64
99
+ sp = "rsp"
100
+ word_size = 8
smallworld/logging.py ADDED
@@ -0,0 +1,90 @@
1
+ import logging
2
+ import sys
3
+
4
+
5
+ class CharacterLevelFilter(logging.Filter):
6
+ """Adds logging level as a single character for formatting."""
7
+
8
+ CHARACTERS = {
9
+ logging.DEBUG: "-",
10
+ logging.INFO: "+",
11
+ logging.WARNING: "!",
12
+ logging.ERROR: "*",
13
+ logging.CRITICAL: "#",
14
+ }
15
+
16
+ def filter(self, record):
17
+ record.levelchar = self.CHARACTERS.get(record.levelno, " ")
18
+ return True
19
+
20
+
21
+ class ColorLevelFilter(logging.Filter):
22
+ """Adds logging level as a color for formatting."""
23
+
24
+ WHITE_DIM = "\x1b[37;2m"
25
+ WHITE = "\x1b[37m"
26
+ YELLOW = "\x1b[33m"
27
+ RED = "\x1b[31m"
28
+ RED_BOLD = "\x1b[31;1m"
29
+ END = "\x1b[0m"
30
+ NULL = END
31
+
32
+ COLORS = {
33
+ logging.DEBUG: WHITE_DIM,
34
+ logging.INFO: WHITE,
35
+ logging.WARNING: YELLOW,
36
+ logging.ERROR: RED,
37
+ logging.CRITICAL: RED_BOLD,
38
+ }
39
+
40
+ def filter(self, record):
41
+ record.levelcolor = self.COLORS.get(record.levelno, self.NULL)
42
+ return True
43
+
44
+
45
+ def setup_logging(
46
+ level: int = logging.INFO,
47
+ verbose: bool = False,
48
+ colors: bool = True,
49
+ clear: bool = True,
50
+ ) -> None:
51
+ """Setup log handling.
52
+
53
+ Note: this should only be called once.
54
+
55
+ Arguments:
56
+ level: Logging level (from `logging` module).
57
+ verbose: Enable verbose logging mode.
58
+ colors: Enable logging colors (if supported).
59
+ clear: Remove all other handlers from the root logger.
60
+ """
61
+
62
+ if verbose:
63
+ format = "[%(asctime)s %(levelname)-7s|%(name)s]: %(message)s"
64
+ else:
65
+ format = "[%(levelchar)s] %(message)s"
66
+
67
+ if colors and sys.stderr.isatty():
68
+ format = f"%(levelcolor)s{format}{ColorLevelFilter.END}"
69
+
70
+ root = logging.getLogger()
71
+ root.setLevel(level)
72
+
73
+ if clear:
74
+ handlers = list(root.handlers)
75
+ for handler in handlers:
76
+ root.removeHandler(handler)
77
+
78
+ formatter = logging.Formatter(format)
79
+
80
+ handler = logging.StreamHandler()
81
+ handler.setLevel(level)
82
+ handler.addFilter(CharacterLevelFilter())
83
+ handler.addFilter(ColorLevelFilter())
84
+
85
+ handler.setFormatter(formatter)
86
+
87
+ root.addHandler(handler)
88
+
89
+
90
+ __all__ = ["setup_logging"]
@@ -0,0 +1,95 @@
1
+ import enum
2
+ from dataclasses import dataclass
3
+
4
+
5
+ class Architecture(enum.Enum):
6
+ """Architecture and mode.
7
+
8
+ Names take the form ``{ARCH}_{MODE}`` where ``{ARCH}`` and ``{MODE}``
9
+ match the regex ``[A-Z0-9]+``.
10
+
11
+ Values are lowercase, kebab-case.
12
+ """
13
+
14
+ X86_32 = "x86-32"
15
+ """32-bit x86 supporting SSE extensions."""
16
+
17
+ X86_64 = "x86-64"
18
+ """64-bit x86 supporting AVX2 extensions."""
19
+
20
+ X86_64_AVX512 = "x86-64-avx512"
21
+ """64-bit x86 supporting AVX512 extensions."""
22
+
23
+ AARCH64 = "aarch64"
24
+
25
+ MIPS32 = "mips32"
26
+
27
+ MIPS64 = "mips64"
28
+
29
+ POWERPC64 = "powerpc64"
30
+ POWERPC32 = "powerpc32"
31
+
32
+ ARM_V5T = "arm-v5t"
33
+ ARM_V6M = "arm-v6m"
34
+ ARM_V6M_THUMB = "arm-v6m-thumb"
35
+ ARM_V7M = "arm-v7m"
36
+ ARM_V7R = "arm-v7r"
37
+ ARM_V7A = "arm-v7a"
38
+
39
+ RISCV64 = "riscv-64"
40
+
41
+ XTENSA = "xtensa"
42
+
43
+
44
+ class Byteorder(enum.Enum):
45
+ """Endianness."""
46
+
47
+ BIG = "big"
48
+ """Big endian - most significant bit first."""
49
+
50
+ LITTLE = "little"
51
+ """Little endian - least significant bit first."""
52
+
53
+ MIDDLE = "middle"
54
+ """Middle endian - also known as PDP-endian."""
55
+
56
+
57
+ class ABI(enum.Enum):
58
+ """Application binary interface.
59
+
60
+ Names match the regex ``[A-Z]+``.
61
+
62
+ Values are lowercase, kebab-case.
63
+ """
64
+
65
+ SYSTEMV = "system-v"
66
+ """System V."""
67
+
68
+ CDECL = "cdecl"
69
+ """Microsoft cdecl."""
70
+
71
+ VECTORCALL = "vectorcall"
72
+ """Microsoft vectorcall."""
73
+
74
+ FASTCALL = "fastcall"
75
+ """Microsoft fastcall."""
76
+
77
+ NONE = "none"
78
+ """No ABI"""
79
+
80
+
81
+ @dataclass(frozen=True)
82
+ class Platform:
83
+ """Platform metadata/configuration storage class."""
84
+
85
+ architecture: Architecture
86
+ """Architecture and mode."""
87
+
88
+ byteorder: Byteorder
89
+ """Endianness."""
90
+
91
+ def __repr__(self) -> str:
92
+ return f"{self.architecture}:{self.byteorder}"
93
+
94
+
95
+ __all__ = ["Platform", "Architecture", "Byteorder", "ABI"]
smallworld/py.typed ADDED
File without changes
@@ -0,0 +1,6 @@
1
+ from . import cpus, memory, models
2
+ from .state import * # noqa: F401, F403
3
+ from .state import __all__ as __state__
4
+ from .unstable import * # noqa: F401, F403
5
+
6
+ __all__ = __state__ + ["cpus", "models", "memory"]
@@ -0,0 +1,32 @@
1
+ from .aarch64 import AArch64
2
+ from .amd64 import AMD64
3
+ from .arm import ARMv5T, ARMv6M, ARMv6MThumb, ARMv7A, ARMv7M, ARMv7R
4
+ from .cpu import * # noqa: F401, F403
5
+ from .cpu import __all__ as __cpu__
6
+ from .i386 import I386
7
+ from .mips import MIPSBE, MIPSEL
8
+ from .mips64 import MIPS64BE, MIPS64EL
9
+ from .powerpc import PowerPC32, PowerPC64
10
+ from .riscv import RISCV64
11
+ from .xtensa import XTensaBE, XTensaEL
12
+
13
+ __all__ = __cpu__ + [
14
+ "AArch64",
15
+ "AMD64",
16
+ "ARMv5T",
17
+ "ARMv6M",
18
+ "ARMv6MThumb",
19
+ "ARMv7M",
20
+ "ARMv7R",
21
+ "ARMv7A",
22
+ "I386",
23
+ "MIPS64EL",
24
+ "MIPS64BE",
25
+ "MIPSEL",
26
+ "MIPSBE",
27
+ "PowerPC32",
28
+ "PowerPC64",
29
+ "RISCV64",
30
+ "XTensaBE",
31
+ "XTensaEL",
32
+ ]