objutils 0.10.5__tar.gz → 0.10.7__tar.gz
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.
- {objutils-0.10.5 → objutils-0.10.7}/PKG-INFO +4 -4
- {objutils-0.10.5 → objutils-0.10.7}/objutils/__init__.py +1 -1
- {objutils-0.10.5 → objutils-0.10.7}/objutils/dwarf/readers.py +3 -3
- {objutils-0.10.5 → objutils-0.10.7}/objutils/dwarf/sm.py +155 -89
- {objutils-0.10.5 → objutils-0.10.7}/objutils/dwarf/traverser.py +134 -1
- {objutils-0.10.5 → objutils-0.10.7}/objutils/elf/defs.py +76 -2
- {objutils-0.10.5 → objutils-0.10.7}/objutils/pecoff/__init__.py +0 -12
- {objutils-0.10.5 → objutils-0.10.7}/objutils/pecoff/pdb/__init__.py +1446 -1056
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_coff_syms.py +5 -3
- objutils-0.10.7/objutils/symbols.py +442 -0
- objutils-0.10.7/objutils/tests/test_sm.py +61 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/version.py +1 -1
- {objutils-0.10.5 → objutils-0.10.7}/pyproject.toml +6 -6
- objutils-0.10.5/objutils/dwarf/.traverser.py.un~ +0 -0
- objutils-0.10.5/objutils/tests/test_sm.py +0 -19
- {objutils-0.10.5 → objutils-0.10.7}/CMakeLists.txt +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/LICENSE +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/build_ext.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/docs/README.rst +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/.coveragerc +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/.vscode/launch.json +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/.vscode/settings.json +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/a2l_test.shf +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/ash.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/binfile.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/checksums.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/cosmac.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/dwarf/__init__.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/dwarf/attrparser.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/dwarf/c_generator.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/dwarf/constants.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/dwarf/encoding.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/dwarf/lineprog.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/elf/__init__.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/elf/arm/__init__.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/elf/arm/attributes.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/elf/model.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/emon52.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/etek.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/exceptions.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/extensions/__init__.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/extensions/ctre.hpp +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/extensions/difflib.h +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/extensions/exceptions.cpp +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/extensions/exceptions.hpp +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/extensions/hexfile.cpp +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/extensions/wrapper.cpp +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/fpc.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/hexdump.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/hexfile.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/ieee695.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/ihex.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/image.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/logger.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/mostec.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/objutils.code-workspace +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/pecoff/defs.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/pecoff/model.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/pickleif.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/rca.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/readers.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/registry.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/arduino_build_artifacts.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_cgen.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_coff_extract.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_coff_import.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_coff_info.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_dwarf_import.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_dwarf_info.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_elf_arm_attrs.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_elf_extract.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_elf_import.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_elf_info.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_elf_syms.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/scripts/oj_hex_info.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/section.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/shf.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/sig.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/srec.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tek.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/__init__.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_arm_attributes.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_ash.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_c_generator.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_checksums.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_cygpath.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_diff_bin.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_elf.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_emon52.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_etek.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_examples_cgen.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_fpc.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_hexdump.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_hexfile.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_ihex.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_image.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_mostec.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_readers.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_registry.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_repr.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_section.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_section_join.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_shf.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_srec.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_tek.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/tests/test_titext.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/titxt.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/utils/__init__.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/utils/arduino.py +0 -0
- {objutils-0.10.5 → objutils-0.10.7}/objutils/utils/diff.py +0 -0
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: objutils
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.7
|
|
4
4
|
Summary: Objectfile library for Python
|
|
5
5
|
License: GPLv2
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Keywords: hex files,intel hex,s19,srec,srecords,object files,map files,embedded,microcontroller,ECU,shf,rfc4194
|
|
8
8
|
Author: Christoph Schueler
|
|
9
9
|
Author-email: cpu12.gems@googlemail.com
|
|
10
|
-
Requires-Python: >=3.
|
|
10
|
+
Requires-Python: >=3.10,<4.0
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
|
|
14
14
|
Classifier: License :: Other/Proprietary License
|
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
22
|
Classifier: Topic :: Scientific/Engineering
|
|
23
23
|
Classifier: Topic :: Software Development
|
|
24
24
|
Requires-Dist: construct (>=2.10.70,<3.0.0)
|
|
25
25
|
Requires-Dist: mako (>=1.3.3,<2.0.0)
|
|
26
|
-
Requires-Dist: numpy (
|
|
26
|
+
Requires-Dist: numpy (>=2.2.5)
|
|
27
27
|
Requires-Dist: rich (>=14.2,<15.0)
|
|
28
28
|
Requires-Dist: sqlalchemy (>=2.0.29,<3.0.0)
|
|
29
29
|
Project-URL: Homepage, https://github.com/christoph2/objutils
|
|
@@ -174,7 +174,7 @@ class DwarfReaders:
|
|
|
174
174
|
constants.AttributeForm.DW_FORM_block2,
|
|
175
175
|
constants.AttributeForm.DW_FORM_block4,
|
|
176
176
|
):
|
|
177
|
-
return self.stack_machine.evaluate(expr)
|
|
177
|
+
return self.stack_machine.evaluate(expr).value.value
|
|
178
178
|
elif form in (
|
|
179
179
|
constants.AttributeForm.DW_FORM_data1,
|
|
180
180
|
constants.AttributeForm.DW_FORM_data2,
|
|
@@ -182,13 +182,13 @@ class DwarfReaders:
|
|
|
182
182
|
constants.AttributeForm.DW_FORM_data8,
|
|
183
183
|
constants.AttributeForm.DW_FORM_data16,
|
|
184
184
|
):
|
|
185
|
-
return
|
|
185
|
+
return int(expr)
|
|
186
186
|
elif form == constants.AttributeForm.DW_FORM_udata:
|
|
187
187
|
return ULEB.parse(expr)
|
|
188
188
|
elif form == constants.AttributeForm.DW_FORM_sdata:
|
|
189
189
|
return SLEB.parse(expr)
|
|
190
190
|
elif form in (constants.AttributeForm.DW_FORM_sec_offset, constants.AttributeForm.DW_FORM_loclistx):
|
|
191
|
-
return
|
|
191
|
+
return int(expr)
|
|
192
192
|
else:
|
|
193
193
|
print("Unsupported DWARF expression form:", form, list(expr))
|
|
194
194
|
raise NotImplementedError(f"Unsupported DWARF expression form: {form}")
|
|
@@ -140,58 +140,60 @@ from construct import Array
|
|
|
140
140
|
from objutils.dwarf import constants
|
|
141
141
|
|
|
142
142
|
|
|
143
|
+
@dataclass
|
|
144
|
+
class TypedValue:
|
|
145
|
+
"""Represents a value on the DWARF stack with an associated type.
|
|
146
|
+
|
|
147
|
+
Attributes:
|
|
148
|
+
value: The actual numeric or address value.
|
|
149
|
+
type_offset: Offset of the DW_TAG_base_type in .debug_info,
|
|
150
|
+
or 0 for the generic type.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
value: Any
|
|
154
|
+
type_offset: int = 0 # 0 means generic type
|
|
155
|
+
|
|
156
|
+
def __int__(self):
|
|
157
|
+
return int(self.value)
|
|
158
|
+
|
|
159
|
+
|
|
143
160
|
class Stack:
|
|
144
161
|
"""Simple LIFO stack for DWARF expression evaluation.
|
|
145
162
|
|
|
146
163
|
Provides basic stack operations for the DWARF stack machine.
|
|
147
|
-
Stores
|
|
148
|
-
|
|
149
|
-
Attributes:
|
|
150
|
-
_values: Internal list storing stack contents (private)
|
|
151
|
-
|
|
152
|
-
Example:
|
|
153
|
-
```python
|
|
154
|
-
stack = Stack()
|
|
155
|
-
stack.push(42)
|
|
156
|
-
stack.push(10)
|
|
157
|
-
result = stack.pop() # 10
|
|
158
|
-
top = stack.tos # 42
|
|
159
|
-
stack.tos = 100 # Modify top without pop/push
|
|
160
|
-
```
|
|
164
|
+
Stores TypedValue instances.
|
|
161
165
|
"""
|
|
162
166
|
|
|
163
167
|
def __init__(self):
|
|
164
168
|
"""Initialize empty stack."""
|
|
165
|
-
self._values: list[
|
|
169
|
+
self._values: list[TypedValue] = []
|
|
166
170
|
|
|
167
|
-
def push(self, value: Any) -> None:
|
|
171
|
+
def push(self, value: Any, type_offset: int = 0) -> None:
|
|
168
172
|
"""Push value onto stack.
|
|
169
173
|
|
|
170
174
|
Args:
|
|
171
|
-
value: Value to push (typically int or address)
|
|
175
|
+
value: Value to push (typically int or address) or TypedValue
|
|
176
|
+
type_offset: Offset of the base type (0 for generic)
|
|
172
177
|
"""
|
|
173
|
-
|
|
178
|
+
if isinstance(value, TypedValue):
|
|
179
|
+
self._values.append(value)
|
|
180
|
+
else:
|
|
181
|
+
self._values.append(TypedValue(value, type_offset))
|
|
174
182
|
|
|
175
|
-
def pop(self) ->
|
|
183
|
+
def pop(self) -> TypedValue:
|
|
176
184
|
"""Pop and return top value from stack.
|
|
177
185
|
|
|
178
186
|
Returns:
|
|
179
|
-
Top stack
|
|
180
|
-
|
|
181
|
-
Raises:
|
|
182
|
-
IndexError: If stack is empty
|
|
187
|
+
Top stack TypedValue
|
|
183
188
|
"""
|
|
184
189
|
return self._values.pop()
|
|
185
190
|
|
|
186
191
|
@property
|
|
187
|
-
def tos(self) ->
|
|
192
|
+
def tos(self) -> TypedValue:
|
|
188
193
|
"""Get top-of-stack value without popping.
|
|
189
194
|
|
|
190
195
|
Returns:
|
|
191
|
-
Top stack
|
|
192
|
-
|
|
193
|
-
Raises:
|
|
194
|
-
IndexError: If stack is empty
|
|
196
|
+
Top stack TypedValue
|
|
195
197
|
"""
|
|
196
198
|
return self._values[-1]
|
|
197
199
|
|
|
@@ -200,36 +202,22 @@ class Stack:
|
|
|
200
202
|
"""Set top-of-stack value without popping.
|
|
201
203
|
|
|
202
204
|
Args:
|
|
203
|
-
value: New value for top of stack
|
|
204
|
-
|
|
205
|
-
Raises:
|
|
206
|
-
IndexError: If stack is empty
|
|
205
|
+
value: New value or TypedValue for top of stack
|
|
207
206
|
"""
|
|
208
|
-
|
|
207
|
+
if isinstance(value, TypedValue):
|
|
208
|
+
self._values[-1] = value
|
|
209
|
+
else:
|
|
210
|
+
current_type = self._values[-1].type_offset
|
|
211
|
+
self._values[-1] = TypedValue(value, current_type)
|
|
209
212
|
|
|
210
|
-
def get_at(self, index: int) ->
|
|
213
|
+
def get_at(self, index: int) -> TypedValue:
|
|
211
214
|
"""Get value at index from top of stack.
|
|
212
215
|
|
|
213
216
|
Args:
|
|
214
217
|
index: Index from top (0 = top, 1 = second, etc.)
|
|
215
218
|
|
|
216
219
|
Returns:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
Raises:
|
|
220
|
-
IndexError: If index out of range
|
|
221
|
-
|
|
222
|
-
Example:
|
|
223
|
-
>>> stack = Stack()
|
|
224
|
-
>>> stack.push(10) # bottom
|
|
225
|
-
>>> stack.push(20)
|
|
226
|
-
>>> stack.push(30) # top
|
|
227
|
-
>>> stack.get_at(0) # 30 (top)
|
|
228
|
-
30
|
|
229
|
-
>>> stack.get_at(1) # 20
|
|
230
|
-
20
|
|
231
|
-
>>> stack.get_at(2) # 10
|
|
232
|
-
10
|
|
220
|
+
TypedValue at specified index
|
|
233
221
|
"""
|
|
234
222
|
return self._values[-(index + 1)]
|
|
235
223
|
|
|
@@ -246,20 +234,6 @@ class Stack:
|
|
|
246
234
|
return f"Stack({self._values!r})"
|
|
247
235
|
|
|
248
236
|
|
|
249
|
-
@dataclass
|
|
250
|
-
class EvaluationResult:
|
|
251
|
-
"""Result of DWARF expression evaluation.
|
|
252
|
-
|
|
253
|
-
Placeholder for future expansion. Could contain:
|
|
254
|
-
- Final stack state
|
|
255
|
-
- Expression interpretation
|
|
256
|
-
- Error information
|
|
257
|
-
- Location type (memory, register, etc.)
|
|
258
|
-
"""
|
|
259
|
-
|
|
260
|
-
pass
|
|
261
|
-
|
|
262
|
-
|
|
263
237
|
######################
|
|
264
238
|
## Operation Classes ##
|
|
265
239
|
######################
|
|
@@ -736,7 +710,7 @@ class Abs(OperationBase):
|
|
|
736
710
|
|
|
737
711
|
def stack_op(self, stack):
|
|
738
712
|
a = stack.pop()
|
|
739
|
-
stack.push(abs(a))
|
|
713
|
+
stack.push(abs(a.value), a.type_offset)
|
|
740
714
|
|
|
741
715
|
|
|
742
716
|
class And_(OperationBase):
|
|
@@ -750,7 +724,7 @@ class And_(OperationBase):
|
|
|
750
724
|
def stack_op(self, stack):
|
|
751
725
|
b = stack.pop()
|
|
752
726
|
a = stack.pop()
|
|
753
|
-
stack.push(a & b)
|
|
727
|
+
stack.push(a.value & b.value, a.type_offset)
|
|
754
728
|
|
|
755
729
|
|
|
756
730
|
class Div(OperationBase):
|
|
@@ -764,7 +738,7 @@ class Div(OperationBase):
|
|
|
764
738
|
def stack_op(self, stack):
|
|
765
739
|
b = stack.pop()
|
|
766
740
|
a = stack.pop()
|
|
767
|
-
stack.push(a // b)
|
|
741
|
+
stack.push(a.value // b.value, a.type_offset)
|
|
768
742
|
|
|
769
743
|
|
|
770
744
|
class Minus(OperationBase):
|
|
@@ -778,7 +752,7 @@ class Minus(OperationBase):
|
|
|
778
752
|
def stack_op(self, stack):
|
|
779
753
|
b = stack.pop()
|
|
780
754
|
a = stack.pop()
|
|
781
|
-
stack.push(a - b)
|
|
755
|
+
stack.push(a.value - b.value, a.type_offset)
|
|
782
756
|
|
|
783
757
|
|
|
784
758
|
class Mod(OperationBase):
|
|
@@ -792,7 +766,7 @@ class Mod(OperationBase):
|
|
|
792
766
|
def stack_op(self, stack):
|
|
793
767
|
b = stack.pop()
|
|
794
768
|
a = stack.pop()
|
|
795
|
-
stack.push(a % b)
|
|
769
|
+
stack.push(a.value % b.value, a.type_offset)
|
|
796
770
|
|
|
797
771
|
|
|
798
772
|
class Mul(OperationBase):
|
|
@@ -806,7 +780,7 @@ class Mul(OperationBase):
|
|
|
806
780
|
def stack_op(self, stack):
|
|
807
781
|
b = stack.pop()
|
|
808
782
|
a = stack.pop()
|
|
809
|
-
stack.push(a * b)
|
|
783
|
+
stack.push(a.value * b.value, a.type_offset)
|
|
810
784
|
|
|
811
785
|
|
|
812
786
|
class Neg(OperationBase):
|
|
@@ -819,7 +793,7 @@ class Neg(OperationBase):
|
|
|
819
793
|
|
|
820
794
|
def stack_op(self, stack):
|
|
821
795
|
a = stack.pop()
|
|
822
|
-
stack.push(-a)
|
|
796
|
+
stack.push(-a.value, a.type_offset)
|
|
823
797
|
|
|
824
798
|
|
|
825
799
|
class Not_(OperationBase):
|
|
@@ -832,7 +806,7 @@ class Not_(OperationBase):
|
|
|
832
806
|
|
|
833
807
|
def stack_op(self, stack):
|
|
834
808
|
a = stack.pop()
|
|
835
|
-
stack.push(~a)
|
|
809
|
+
stack.push(~a.value, a.type_offset)
|
|
836
810
|
|
|
837
811
|
|
|
838
812
|
class Or_(OperationBase):
|
|
@@ -846,7 +820,7 @@ class Or_(OperationBase):
|
|
|
846
820
|
def stack_op(self, stack):
|
|
847
821
|
b = stack.pop()
|
|
848
822
|
a = stack.pop()
|
|
849
|
-
stack.push(a | b)
|
|
823
|
+
stack.push(a.value | b.value, a.type_offset)
|
|
850
824
|
|
|
851
825
|
|
|
852
826
|
class Plus(OperationBase):
|
|
@@ -860,7 +834,7 @@ class Plus(OperationBase):
|
|
|
860
834
|
def stack_op(self, stack):
|
|
861
835
|
b = stack.pop()
|
|
862
836
|
a = stack.pop()
|
|
863
|
-
stack.push(a + b)
|
|
837
|
+
stack.push(a.value + b.value, a.type_offset)
|
|
864
838
|
|
|
865
839
|
|
|
866
840
|
class Plus_Uconst(OperationBase):
|
|
@@ -879,9 +853,18 @@ class Plus_Uconst(OperationBase):
|
|
|
879
853
|
PARAMETERS = ["uleb"]
|
|
880
854
|
|
|
881
855
|
def stack_op(self, stack):
|
|
882
|
-
|
|
856
|
+
try:
|
|
857
|
+
a = stack.pop()
|
|
858
|
+
val = a.value
|
|
859
|
+
type_offset = a.type_offset
|
|
860
|
+
except IndexError:
|
|
861
|
+
# Note: many location expressions (like for member offsets)
|
|
862
|
+
# assume a base address is already on the stack.
|
|
863
|
+
# If the stack is empty, we treat the base as 0.
|
|
864
|
+
val = 0
|
|
865
|
+
type_offset = 0
|
|
883
866
|
constant = self.result[0]
|
|
884
|
-
stack.push(
|
|
867
|
+
stack.push(val + constant, type_offset)
|
|
885
868
|
|
|
886
869
|
|
|
887
870
|
class Shl(OperationBase):
|
|
@@ -893,9 +876,9 @@ class Shl(OperationBase):
|
|
|
893
876
|
DISPLAY_NAME = "shl"
|
|
894
877
|
|
|
895
878
|
def stack_op(self, stack):
|
|
896
|
-
shift = stack.pop()
|
|
879
|
+
shift = stack.pop().value
|
|
897
880
|
value = stack.pop()
|
|
898
|
-
stack.push(value << shift)
|
|
881
|
+
stack.push(value.value << shift, value.type_offset)
|
|
899
882
|
|
|
900
883
|
|
|
901
884
|
class Shr(OperationBase):
|
|
@@ -907,9 +890,9 @@ class Shr(OperationBase):
|
|
|
907
890
|
DISPLAY_NAME = "shr"
|
|
908
891
|
|
|
909
892
|
def stack_op(self, stack):
|
|
910
|
-
shift = stack.pop()
|
|
893
|
+
shift = stack.pop().value
|
|
911
894
|
value = stack.pop()
|
|
912
|
-
stack.push(value >> shift)
|
|
895
|
+
stack.push(value.value >> shift, value.type_offset)
|
|
913
896
|
|
|
914
897
|
|
|
915
898
|
class Shra(OperationBase):
|
|
@@ -921,10 +904,10 @@ class Shra(OperationBase):
|
|
|
921
904
|
DISPLAY_NAME = "shra"
|
|
922
905
|
|
|
923
906
|
def stack_op(self, stack):
|
|
924
|
-
shift = stack.pop()
|
|
907
|
+
shift = stack.pop().value
|
|
925
908
|
value = stack.pop()
|
|
926
909
|
# Python's >> is arithmetic for negative numbers
|
|
927
|
-
stack.push(value >> shift)
|
|
910
|
+
stack.push(value.value >> shift, value.type_offset)
|
|
928
911
|
|
|
929
912
|
|
|
930
913
|
class Xor(OperationBase):
|
|
@@ -938,7 +921,7 @@ class Xor(OperationBase):
|
|
|
938
921
|
def stack_op(self, stack):
|
|
939
922
|
b = stack.pop()
|
|
940
923
|
a = stack.pop()
|
|
941
|
-
stack.push(a ^ b)
|
|
924
|
+
stack.push(a.value ^ b.value, a.type_offset)
|
|
942
925
|
|
|
943
926
|
|
|
944
927
|
#############################
|
|
@@ -1908,6 +1891,11 @@ class Addrx(OperationBase):
|
|
|
1908
1891
|
DISPLAY_NAME = "addrx"
|
|
1909
1892
|
PARAMETERS = ["uleb"]
|
|
1910
1893
|
|
|
1894
|
+
def stack_op(self, stack):
|
|
1895
|
+
index = self.result[0]
|
|
1896
|
+
# In a real implementation, we would look up the address in .debug_addr
|
|
1897
|
+
stack.push(0)
|
|
1898
|
+
|
|
1911
1899
|
|
|
1912
1900
|
class Constx(OperationBase):
|
|
1913
1901
|
"""DW_OP_constx: Push constant from .debug_addr. Stack Effect: [] -> [constant]"""
|
|
@@ -1915,6 +1903,11 @@ class Constx(OperationBase):
|
|
|
1915
1903
|
DISPLAY_NAME = "constx"
|
|
1916
1904
|
PARAMETERS = ["uleb"]
|
|
1917
1905
|
|
|
1906
|
+
def stack_op(self, stack):
|
|
1907
|
+
index = self.result[0]
|
|
1908
|
+
# In a real implementation, we would look up the constant in .debug_addr
|
|
1909
|
+
stack.push(0)
|
|
1910
|
+
|
|
1918
1911
|
|
|
1919
1912
|
class Entry_Value(OperationBase):
|
|
1920
1913
|
"""DW_OP_entry_value: Value at function entry. Stack Effect: varies"""
|
|
@@ -1929,6 +1922,21 @@ class Const_Type(OperationBase):
|
|
|
1929
1922
|
DISPLAY_NAME = "const_type"
|
|
1930
1923
|
PARAMETERS = ["uleb", "u8"]
|
|
1931
1924
|
|
|
1925
|
+
def parse(self, image):
|
|
1926
|
+
super().parse(image)
|
|
1927
|
+
size = self.result[1]
|
|
1928
|
+
self.data_block = image.read(size)
|
|
1929
|
+
|
|
1930
|
+
def stack_op(self, stack):
|
|
1931
|
+
type_offset = self.result[0]
|
|
1932
|
+
# For simplicity, we interpret the data block as an integer
|
|
1933
|
+
# In a real implementation, we would use the type information
|
|
1934
|
+
value = int.from_bytes(self.data_block, byteorder="little") # Assuming little-endian for now
|
|
1935
|
+
stack.push(value, type_offset)
|
|
1936
|
+
|
|
1937
|
+
def __str__(self):
|
|
1938
|
+
return f"{self.DISPLAY_NAME}(type_offset={self.result[0]}, size={self.result[1]}, value=0x{self.data_block.hex()})"
|
|
1939
|
+
|
|
1932
1940
|
|
|
1933
1941
|
class Regval_Type(OperationBase):
|
|
1934
1942
|
"""DW_OP_regval_type: Typed register value. Stack Effect: [] -> [value]"""
|
|
@@ -1936,6 +1944,13 @@ class Regval_Type(OperationBase):
|
|
|
1936
1944
|
DISPLAY_NAME = "regval_type"
|
|
1937
1945
|
PARAMETERS = ["uleb", "uleb"]
|
|
1938
1946
|
|
|
1947
|
+
def stack_op(self, stack):
|
|
1948
|
+
reg_num = self.result[0]
|
|
1949
|
+
type_offset = self.result[1]
|
|
1950
|
+
# In a real implementation, we would fetch the register value here
|
|
1951
|
+
# For now, we push a placeholder
|
|
1952
|
+
stack.push(0, type_offset)
|
|
1953
|
+
|
|
1939
1954
|
|
|
1940
1955
|
class Deref_Type(OperationBase):
|
|
1941
1956
|
"""DW_OP_deref_type: Typed dereference. Stack Effect: [address] -> [typed_value]"""
|
|
@@ -1943,6 +1958,13 @@ class Deref_Type(OperationBase):
|
|
|
1943
1958
|
DISPLAY_NAME = "deref_type"
|
|
1944
1959
|
PARAMETERS = ["u8", "uleb"]
|
|
1945
1960
|
|
|
1961
|
+
def stack_op(self, stack):
|
|
1962
|
+
addr = stack.pop().value
|
|
1963
|
+
# size = self.result[0]
|
|
1964
|
+
type_offset = self.result[1]
|
|
1965
|
+
# In a real implementation, we would read from memory here
|
|
1966
|
+
stack.push(0, type_offset)
|
|
1967
|
+
|
|
1946
1968
|
|
|
1947
1969
|
class Xderef_Type(OperationBase):
|
|
1948
1970
|
"""DW_OP_xderef_type: Typed extended dereference. Stack Effect: [addr_space, address] -> [typed_value]"""
|
|
@@ -1950,6 +1972,14 @@ class Xderef_Type(OperationBase):
|
|
|
1950
1972
|
DISPLAY_NAME = "xderef_type"
|
|
1951
1973
|
PARAMETERS = ["u8", "uleb"]
|
|
1952
1974
|
|
|
1975
|
+
def stack_op(self, stack):
|
|
1976
|
+
addr = stack.pop().value
|
|
1977
|
+
# addr_space = stack.pop().value
|
|
1978
|
+
# size = self.result[0]
|
|
1979
|
+
type_offset = self.result[1]
|
|
1980
|
+
# In a real implementation, we would read from memory here
|
|
1981
|
+
stack.push(0, type_offset)
|
|
1982
|
+
|
|
1953
1983
|
|
|
1954
1984
|
class Convert(OperationBase):
|
|
1955
1985
|
"""DW_OP_convert: Convert value to different type. Stack Effect: [value] -> [converted_value]"""
|
|
@@ -1957,6 +1987,11 @@ class Convert(OperationBase):
|
|
|
1957
1987
|
DISPLAY_NAME = "convert"
|
|
1958
1988
|
PARAMETERS = ["uleb"]
|
|
1959
1989
|
|
|
1990
|
+
def stack_op(self, stack):
|
|
1991
|
+
val = stack.pop()
|
|
1992
|
+
new_type = self.result[0]
|
|
1993
|
+
stack.push(val.value, new_type)
|
|
1994
|
+
|
|
1960
1995
|
|
|
1961
1996
|
class Reinterpret(OperationBase):
|
|
1962
1997
|
"""DW_OP_reinterpret: Reinterpret value as different type. Stack Effect: [value] -> [reinterpreted_value]"""
|
|
@@ -1964,6 +1999,11 @@ class Reinterpret(OperationBase):
|
|
|
1964
1999
|
DISPLAY_NAME = "reinterpret"
|
|
1965
2000
|
PARAMETERS = ["uleb"]
|
|
1966
2001
|
|
|
2002
|
+
def stack_op(self, stack):
|
|
2003
|
+
val = stack.pop()
|
|
2004
|
+
new_type = self.result[0]
|
|
2005
|
+
stack.push(val.value, new_type)
|
|
2006
|
+
|
|
1967
2007
|
|
|
1968
2008
|
##################################
|
|
1969
2009
|
## Vendor-Specific Extensions ##
|
|
@@ -2301,11 +2341,28 @@ OP_MAP = {
|
|
|
2301
2341
|
constants.Operation.PGI_omp_thread_num: Gi_Omp_Thread_Num,
|
|
2302
2342
|
}
|
|
2303
2343
|
|
|
2344
|
+
|
|
2304
2345
|
######################
|
|
2305
2346
|
######################
|
|
2306
2347
|
######################
|
|
2307
2348
|
|
|
2308
2349
|
|
|
2350
|
+
@dataclass(frozen=True)
|
|
2351
|
+
class EvaluationResult:
|
|
2352
|
+
"""Result of DWARF expression evaluation.
|
|
2353
|
+
|
|
2354
|
+
Future expansion could contain:
|
|
2355
|
+
- Final stack state
|
|
2356
|
+
- Expression interpretation
|
|
2357
|
+
- Error information
|
|
2358
|
+
- Location type (memory, register, etc.)
|
|
2359
|
+
|
|
2360
|
+
"""
|
|
2361
|
+
|
|
2362
|
+
value: TypedValue
|
|
2363
|
+
representation: str
|
|
2364
|
+
|
|
2365
|
+
|
|
2309
2366
|
class StackMachine:
|
|
2310
2367
|
"""DWARF expression stack machine evaluator.
|
|
2311
2368
|
|
|
@@ -2365,14 +2422,23 @@ class StackMachine:
|
|
|
2365
2422
|
try:
|
|
2366
2423
|
opcode = OPs(opcode_num)
|
|
2367
2424
|
except ValueError:
|
|
2368
|
-
print(f"Opcode not found {opcode_num!r}")
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2425
|
+
# print(f"Opcode not found {opcode_num!r}")
|
|
2426
|
+
result.append(f"<unk>({opcode_num:#x})")
|
|
2427
|
+
continue
|
|
2428
|
+
|
|
2372
2429
|
op_klass = OP_MAP.get(opcode_num)
|
|
2373
2430
|
if op_klass:
|
|
2374
2431
|
operation = op_klass()
|
|
2375
2432
|
operation.parse(image)
|
|
2376
2433
|
result.append(str(operation))
|
|
2377
|
-
|
|
2378
|
-
|
|
2434
|
+
try:
|
|
2435
|
+
operation.stack_op(self.stack)
|
|
2436
|
+
except (IndexError, AttributeError):
|
|
2437
|
+
# Some operations might fail if context is missing
|
|
2438
|
+
pass
|
|
2439
|
+
else:
|
|
2440
|
+
result.append(f"{opcode.name}()")
|
|
2441
|
+
|
|
2442
|
+
# Return summary of executed ops
|
|
2443
|
+
res_val = self.stack.pop() if not self.stack.empty() else None
|
|
2444
|
+
return EvaluationResult(value=res_val, representation="; ".join(result))
|