mapfile_parser 2.12.2__tar.gz → 2.13.0__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.
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/CHANGELOG.md +22 -1
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/Cargo.lock +1 -1
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/Cargo.toml +1 -1
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/PKG-INFO +2 -2
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/README.md +1 -1
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/pyproject.toml +1 -1
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/__init__.py +1 -1
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/sym_info.py +36 -19
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/mapfile.py +175 -43
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/mapfile_parser.pyi +6 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/found_symbol_info.rs +33 -21
- mapfile_parser-2.13.0/src/rs/iterators/iter_mapfile_syms_by_name.rs +58 -0
- mapfile_parser-2.13.0/src/rs/iterators/iter_mapfile_syms_by_vram.rs +50 -0
- mapfile_parser-2.13.0/src/rs/iterators/iter_mapfile_syms_by_vrom.rs +50 -0
- mapfile_parser-2.13.0/src/rs/iterators/iter_segment_syms_by_name.rs +55 -0
- mapfile_parser-2.13.0/src/rs/iterators/mod.rs +12 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/lib.rs +3 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/mapfile.rs +19 -2
- mapfile_parser-2.13.0/src/rs/maybe_found_symbol_info.rs +66 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/parser.rs +1 -1
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/section.rs +74 -45
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/segment.rs +55 -2
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/symbol.rs +28 -4
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/symbol_decomp_state.rs +1 -1
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/.gitattributes +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/.gitignore +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/LICENSE +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/__main__.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/__init__.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/bss_check.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/first_diff.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/jsonify.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/objdiff_report.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/pj64_syms.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/progress.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/symbol_sizes_csv.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/frontends/upload_frogress.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/internals/__init__.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/internals/objdiff_report.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/mapfile_rs.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/progress_stats.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/progress_stats_rs.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/mapfile_parser/utils.py +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/maps_comparison_info.rs +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/progress_stats.rs +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/report.rs +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/symbol_comparison_info.rs +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/src/rs/utils.rs +0 -0
- {mapfile_parser-2.12.2 → mapfile_parser-2.13.0}/uv.lock +0 -0
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.13.0] - 2026-06-28
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `findPossibleSymbolsByVram`, `findPossibleSymbolsByVrom`, and
|
|
15
|
+
`findPossibleSymbolsByName` for `MapFile` and `findPossibleSymbolByVram`,
|
|
16
|
+
`findPossibleSymbolByVrom`, and `findPossibleSymbolsByName` for `Segment`.
|
|
17
|
+
- Allow iterating over the mapfile looking for multiple symbols that could
|
|
18
|
+
match either the vram, vrom or name given instead of stopping at the first
|
|
19
|
+
one that matches the criteria.
|
|
20
|
+
- `Symbol::isNonmatching`: If true, the current symbol is a `.NON_MATCHING`
|
|
21
|
+
marker symbol.
|
|
22
|
+
- `Section::containsVram`, `Section::containsVrom`, `Segment::containsVram`,
|
|
23
|
+
`Segment::containsVrom`.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- `sym_info` now iterates over every possible vram/vrom address for every
|
|
28
|
+
segment instead of only printing the first found one.
|
|
29
|
+
|
|
10
30
|
## [2.12.2] - 2026-05-30
|
|
11
31
|
|
|
12
32
|
### Fixed
|
|
@@ -708,8 +728,9 @@ Full changes: <https://github.com/Decompollaborate/mapfile_parser/compare/702a73
|
|
|
708
728
|
|
|
709
729
|
- Initial release
|
|
710
730
|
|
|
711
|
-
[unreleased]: https://github.com/Decompollaborate/mapfile_parser/compare/2.
|
|
731
|
+
[unreleased]: https://github.com/Decompollaborate/mapfile_parser/compare/2.13.0...HEAD
|
|
712
732
|
|
|
733
|
+
[2.13.0]: https://github.com/Decompollaborate/mapfile_parser/compare/2.21.2...2.13.0
|
|
713
734
|
[2.12.2]: https://github.com/Decompollaborate/mapfile_parser/compare/2.21.1...2.12.2
|
|
714
735
|
[2.12.1]: https://github.com/Decompollaborate/mapfile_parser/compare/2.21.0...2.12.1
|
|
715
736
|
[2.12.0]: https://github.com/Decompollaborate/mapfile_parser/compare/2.11.0...2.12.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mapfile_parser
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.13.0
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
@@ -90,7 +90,7 @@ cargo add mapfile_parser
|
|
|
90
90
|
Or add the following line manually to your `Cargo.toml` file:
|
|
91
91
|
|
|
92
92
|
```toml
|
|
93
|
-
mapfile_parser = "2.
|
|
93
|
+
mapfile_parser = "2.13"
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
## Versioning and changelog
|
|
@@ -9,6 +9,7 @@ import argparse
|
|
|
9
9
|
from collections.abc import Callable
|
|
10
10
|
import decomp_settings
|
|
11
11
|
from pathlib import Path
|
|
12
|
+
from typing import Generator
|
|
12
13
|
|
|
13
14
|
from .. import mapfile
|
|
14
15
|
from .. import utils
|
|
@@ -31,36 +32,52 @@ def doSymInfo(
|
|
|
31
32
|
if plfResolver is not None:
|
|
32
33
|
mapFile = mapFile.resolvePartiallyLinkedFiles(plfResolver)
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
count = 0
|
|
36
|
+
for info in iterateSymbols(
|
|
37
|
+
mapFile,
|
|
38
|
+
symName,
|
|
39
|
+
as_vram,
|
|
40
|
+
as_vrom,
|
|
41
|
+
as_name,
|
|
42
|
+
):
|
|
43
|
+
print(info.getAsStrPlusOffset(symName))
|
|
44
|
+
count += 1
|
|
45
|
+
|
|
46
|
+
if count == 0:
|
|
47
|
+
print(f"'{symName}' not found in map file '{mapPath}'")
|
|
48
|
+
return 1
|
|
49
|
+
return 0
|
|
50
|
+
|
|
35
51
|
|
|
52
|
+
def iterateSymbols(
|
|
53
|
+
mapFile: mapfile.MapFile,
|
|
54
|
+
symName: str,
|
|
55
|
+
as_vram: bool,
|
|
56
|
+
as_vrom: bool,
|
|
57
|
+
as_name: bool,
|
|
58
|
+
) -> Generator[mapfile.MaybeFoundSymbolInfo]:
|
|
36
59
|
if as_vram:
|
|
37
60
|
address = int(symName, 0)
|
|
38
|
-
info
|
|
61
|
+
for info in mapFile.findPossibleSymbolsByVram(address):
|
|
62
|
+
yield info
|
|
39
63
|
elif as_vrom:
|
|
40
64
|
address = int(symName, 0)
|
|
41
|
-
info
|
|
65
|
+
for info in mapFile.findPossibleSymbolsByVrom(address):
|
|
66
|
+
yield info
|
|
42
67
|
elif as_name:
|
|
43
|
-
info
|
|
68
|
+
for info in mapFile.findPossibleSymbolsByName(symName):
|
|
69
|
+
yield info
|
|
44
70
|
|
|
45
71
|
# Start the guessing game
|
|
46
72
|
elif utils.convertibleToInt(symName, 0):
|
|
47
73
|
address = int(symName, 0)
|
|
48
|
-
info
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
74
|
+
for info in mapFile.findPossibleSymbolsByVram(address):
|
|
75
|
+
yield info
|
|
76
|
+
for info in mapFile.findPossibleSymbolsByVrom(address):
|
|
77
|
+
yield info
|
|
52
78
|
else:
|
|
53
|
-
info
|
|
54
|
-
|
|
55
|
-
if info is not None:
|
|
56
|
-
print(info.getAsStrPlusOffset(symName))
|
|
57
|
-
return 0
|
|
58
|
-
print(f"'{symName}' not found in map file '{mapPath}'")
|
|
59
|
-
if len(possibleFiles) > 0:
|
|
60
|
-
print("But it may be a local symbol of either of the following files:")
|
|
61
|
-
for f in possibleFiles:
|
|
62
|
-
print(f" {f.asStr()})")
|
|
63
|
-
return 1
|
|
79
|
+
for info in mapFile.findPossibleSymbolsByName(symName):
|
|
80
|
+
yield info
|
|
64
81
|
|
|
65
82
|
|
|
66
83
|
def processArguments(
|
|
@@ -40,10 +40,10 @@ class FoundSymbolInfo:
|
|
|
40
40
|
symbol: Symbol
|
|
41
41
|
offset: int = 0
|
|
42
42
|
|
|
43
|
-
def getAsStr(self) -> str:
|
|
44
|
-
return f"'{self.symbol.name}' (VRAM: {self.symbol.getVramStr()}, VROM: {self.symbol.getVromStr()}, SIZE: {self.symbol.getSizeStr()}, {self.section.filepath})"
|
|
43
|
+
def getAsStr(self, *, extra: str = "") -> str:
|
|
44
|
+
return f"'{self.symbol.name}' (VRAM: {self.symbol.getVramStr()}, VROM: {self.symbol.getVromStr()}, SIZE: {self.symbol.getSizeStr()}, {self.section.filepath}{extra})"
|
|
45
45
|
|
|
46
|
-
def getAsStrPlusOffset(self, symName: str | None = None) -> str:
|
|
46
|
+
def getAsStrPlusOffset(self, symName: str | None = None, *, extra: str = "") -> str:
|
|
47
47
|
if self.offset != 0:
|
|
48
48
|
if symName is not None:
|
|
49
49
|
message = symName
|
|
@@ -52,7 +52,29 @@ class FoundSymbolInfo:
|
|
|
52
52
|
message += f" is at 0x{self.offset:X} bytes inside"
|
|
53
53
|
else:
|
|
54
54
|
message = "Symbol"
|
|
55
|
-
return f"{message} {self.getAsStr()}"
|
|
55
|
+
return f"{message} {self.getAsStr(extra=extra)}"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclasses.dataclass
|
|
59
|
+
class MaybeFoundSymbolInfo:
|
|
60
|
+
segment: Segment
|
|
61
|
+
section: Section
|
|
62
|
+
symbol: Symbol | None
|
|
63
|
+
offset: int
|
|
64
|
+
|
|
65
|
+
def getAsStrPlusOffset(self, symName: str) -> str:
|
|
66
|
+
if self.symbol is not None:
|
|
67
|
+
info = FoundSymbolInfo(
|
|
68
|
+
self.section,
|
|
69
|
+
self.symbol,
|
|
70
|
+
self.offset,
|
|
71
|
+
)
|
|
72
|
+
return info.getAsStrPlusOffset(symName, extra=f", SEG: {self.segment.name}")
|
|
73
|
+
|
|
74
|
+
extra = ""
|
|
75
|
+
if self.offset != 0:
|
|
76
|
+
extra = f" at offset 0x{self.offset:X}"
|
|
77
|
+
return f"{symName} may be part of section {self.section.filepath} (segment {self.segment.name}){extra}, but it isn't globally visible."
|
|
56
78
|
|
|
57
79
|
|
|
58
80
|
@dataclasses.dataclass
|
|
@@ -107,6 +129,12 @@ class Symbol:
|
|
|
107
129
|
Note the symbol with the actual `.NON_MATCHING` will have this member
|
|
108
130
|
set to `false`.
|
|
109
131
|
"""
|
|
132
|
+
isNonmatching: bool = False
|
|
133
|
+
"""
|
|
134
|
+
`true` if this symbol has a `.NON_MATCHING` suffix.
|
|
135
|
+
|
|
136
|
+
Note `.NON_MATCHING` marker symbols have size 0.
|
|
137
|
+
"""
|
|
110
138
|
inferredStatic: bool = False
|
|
111
139
|
|
|
112
140
|
def getVramStr(self) -> str:
|
|
@@ -173,6 +201,7 @@ class Symbol:
|
|
|
173
201
|
self.vrom,
|
|
174
202
|
self.align,
|
|
175
203
|
self.nonmatchingSymExists,
|
|
204
|
+
self.isNonmatching,
|
|
176
205
|
self.inferredStatic,
|
|
177
206
|
)
|
|
178
207
|
|
|
@@ -201,6 +230,14 @@ class Section:
|
|
|
201
230
|
def isNoloadSection(self) -> bool:
|
|
202
231
|
return self.sectionType in {".bss", ".sbss", "COMMON", ".scommon"}
|
|
203
232
|
|
|
233
|
+
def containsVram(self, address: int) -> bool:
|
|
234
|
+
return address >= self.vram and address < self.vram + self.size
|
|
235
|
+
|
|
236
|
+
def containsVrom(self, address: int) -> bool | None:
|
|
237
|
+
if self.vrom is None:
|
|
238
|
+
return None
|
|
239
|
+
return address >= self.vrom and address < self.vrom + self.size
|
|
240
|
+
|
|
204
241
|
def serializeVram(self, humanReadable: bool = True) -> str | int | None:
|
|
205
242
|
if humanReadable:
|
|
206
243
|
return f"0x{self.vram:08X}"
|
|
@@ -281,60 +318,76 @@ class Section:
|
|
|
281
318
|
return None
|
|
282
319
|
|
|
283
320
|
def findSymbolByVram(self, address: int) -> tuple[Symbol, int] | None:
|
|
284
|
-
|
|
321
|
+
nonMatchingSym: Symbol | None = None
|
|
285
322
|
|
|
286
323
|
for sym in self._symbols:
|
|
287
324
|
if sym.vram == address:
|
|
325
|
+
# Matching address
|
|
326
|
+
if sym.isNonmatching:
|
|
327
|
+
# Try to avoid non matching marker symbols
|
|
328
|
+
nonMatchingSym = sym
|
|
329
|
+
continue
|
|
288
330
|
return sym, 0
|
|
289
331
|
|
|
290
|
-
if
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
if offset < 0:
|
|
294
|
-
return None
|
|
295
|
-
return prevSym, offset
|
|
332
|
+
if sym.vram > address:
|
|
333
|
+
# We somehow go through the symbol without seeing it?
|
|
334
|
+
break
|
|
296
335
|
|
|
297
|
-
|
|
336
|
+
if sym.size == 0:
|
|
337
|
+
# The only way for a symbol to have size zero is to be a
|
|
338
|
+
# nonmatching marker, usually at least.
|
|
339
|
+
if sym.isNonmatching:
|
|
340
|
+
# Try to avoid non matching marker symbols
|
|
341
|
+
nonMatchingSym = sym
|
|
342
|
+
continue
|
|
298
343
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
return
|
|
344
|
+
if sym.vram < address and address < sym.vram + sym.size:
|
|
345
|
+
if sym.isNonmatching:
|
|
346
|
+
# Try to avoid non matching marker symbols
|
|
347
|
+
nonMatchingSym = sym
|
|
348
|
+
continue
|
|
349
|
+
return sym, address - sym.vram
|
|
305
350
|
|
|
351
|
+
if nonMatchingSym is not None:
|
|
352
|
+
return nonMatchingSym, address - nonMatchingSym.vram
|
|
306
353
|
return None
|
|
307
354
|
|
|
308
355
|
def findSymbolByVrom(self, address: int) -> tuple[Symbol, int] | None:
|
|
309
|
-
|
|
310
|
-
prevSym: Symbol | None = None
|
|
356
|
+
nonMatchingSym: Symbol | None = None
|
|
311
357
|
|
|
312
358
|
for sym in self._symbols:
|
|
359
|
+
if sym.vrom is None:
|
|
360
|
+
continue
|
|
361
|
+
|
|
313
362
|
if sym.vrom == address:
|
|
363
|
+
# Matching address
|
|
364
|
+
if sym.isNonmatching:
|
|
365
|
+
# Try to avoid non matching marker symbols
|
|
366
|
+
nonMatchingSym = sym
|
|
367
|
+
continue
|
|
314
368
|
return sym, 0
|
|
315
369
|
|
|
316
|
-
if
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if offset < 0:
|
|
320
|
-
return None
|
|
321
|
-
return prevSym, offset
|
|
370
|
+
if sym.vrom > address:
|
|
371
|
+
# We somehow go through the symbol without seeing it?
|
|
372
|
+
break
|
|
322
373
|
|
|
323
|
-
if sym.
|
|
324
|
-
|
|
325
|
-
|
|
374
|
+
if sym.size == 0:
|
|
375
|
+
# The only way for a symbol to have size zero is to be a
|
|
376
|
+
# nonmatching marker, usually at least.
|
|
377
|
+
if sym.isNonmatching:
|
|
378
|
+
# Try to avoid non matching marker symbols
|
|
379
|
+
nonMatchingSym = sym
|
|
380
|
+
continue
|
|
326
381
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
offset = address - prevVrom
|
|
334
|
-
if offset < 0:
|
|
335
|
-
return None
|
|
336
|
-
return prevSym, offset
|
|
382
|
+
if sym.vrom < address and address < sym.vrom + sym.size:
|
|
383
|
+
if sym.isNonmatching:
|
|
384
|
+
# Try to avoid non matching marker symbols
|
|
385
|
+
nonMatchingSym = sym
|
|
386
|
+
continue
|
|
387
|
+
return sym, address - sym.vrom
|
|
337
388
|
|
|
389
|
+
if nonMatchingSym is not None and nonMatchingSym.vrom is not None:
|
|
390
|
+
return nonMatchingSym, address - nonMatchingSym.vrom
|
|
338
391
|
return None
|
|
339
392
|
|
|
340
393
|
@staticmethod
|
|
@@ -444,6 +497,14 @@ class Segment:
|
|
|
444
497
|
align: int | None = None
|
|
445
498
|
_sectionsList: list[Section] = dataclasses.field(default_factory=list)
|
|
446
499
|
|
|
500
|
+
def containsVram(self, address: int) -> bool:
|
|
501
|
+
return address >= self.vram and address < self.vram + self.size
|
|
502
|
+
|
|
503
|
+
def containsVrom(self, address: int) -> bool | None:
|
|
504
|
+
if self.vrom is None:
|
|
505
|
+
return None
|
|
506
|
+
return address >= self.vrom and address < self.vrom + self.size
|
|
507
|
+
|
|
447
508
|
def serializeVram(self, humanReadable: bool = True) -> str | int | None:
|
|
448
509
|
if humanReadable:
|
|
449
510
|
return f"0x{self.vram:08X}"
|
|
@@ -498,7 +559,8 @@ class Segment:
|
|
|
498
559
|
return None
|
|
499
560
|
|
|
500
561
|
def findSymbolByVram(
|
|
501
|
-
self,
|
|
562
|
+
self,
|
|
563
|
+
address: int,
|
|
502
564
|
) -> tuple[FoundSymbolInfo | None, list[Section]]:
|
|
503
565
|
possibleFiles: list[Section] = []
|
|
504
566
|
for section in self._sectionsList:
|
|
@@ -506,12 +568,13 @@ class Segment:
|
|
|
506
568
|
if pair is not None:
|
|
507
569
|
sym, offset = pair
|
|
508
570
|
return FoundSymbolInfo(section, sym, offset), []
|
|
509
|
-
if
|
|
571
|
+
if section.containsVram(address):
|
|
510
572
|
possibleFiles.append(section)
|
|
511
573
|
return None, possibleFiles
|
|
512
574
|
|
|
513
575
|
def findSymbolByVrom(
|
|
514
|
-
self,
|
|
576
|
+
self,
|
|
577
|
+
address: int,
|
|
515
578
|
) -> tuple[FoundSymbolInfo | None, list[Section]]:
|
|
516
579
|
possibleFiles: list[Section] = []
|
|
517
580
|
for section in self._sectionsList:
|
|
@@ -521,10 +584,51 @@ class Segment:
|
|
|
521
584
|
if pair is not None:
|
|
522
585
|
sym, offset = pair
|
|
523
586
|
return FoundSymbolInfo(section, sym, offset), []
|
|
524
|
-
if
|
|
587
|
+
if section.containsVrom(address):
|
|
525
588
|
possibleFiles.append(section)
|
|
526
589
|
return None, possibleFiles
|
|
527
590
|
|
|
591
|
+
def findPossibleSymbolByVram(
|
|
592
|
+
self,
|
|
593
|
+
address: int,
|
|
594
|
+
) -> MaybeFoundSymbolInfo | None:
|
|
595
|
+
for section in self._sectionsList:
|
|
596
|
+
if section.containsVram(address):
|
|
597
|
+
pair = section.findSymbolByVram(address)
|
|
598
|
+
if pair is not None:
|
|
599
|
+
sym, offset = pair
|
|
600
|
+
else:
|
|
601
|
+
sym = None
|
|
602
|
+
offset = address - section.vram
|
|
603
|
+
return MaybeFoundSymbolInfo(self, section, sym, offset)
|
|
604
|
+
return None
|
|
605
|
+
|
|
606
|
+
def findPossibleSymbolByVrom(
|
|
607
|
+
self,
|
|
608
|
+
address: int,
|
|
609
|
+
) -> MaybeFoundSymbolInfo | None:
|
|
610
|
+
for section in self._sectionsList:
|
|
611
|
+
if section.vrom is not None and section.containsVrom(address):
|
|
612
|
+
pair = section.findSymbolByVrom(address)
|
|
613
|
+
if pair is not None:
|
|
614
|
+
sym, offset = pair
|
|
615
|
+
else:
|
|
616
|
+
sym = None
|
|
617
|
+
offset = address - section.vram
|
|
618
|
+
return MaybeFoundSymbolInfo(self, section, sym, offset)
|
|
619
|
+
return None
|
|
620
|
+
|
|
621
|
+
def findPossibleSymbolsByName(
|
|
622
|
+
self,
|
|
623
|
+
symName: str,
|
|
624
|
+
) -> Generator[MaybeFoundSymbolInfo]:
|
|
625
|
+
# There may be multiple symbols with the same name in the same segment,
|
|
626
|
+
# so this function iterate over them and yields them all.
|
|
627
|
+
for section in self._sectionsList:
|
|
628
|
+
sym = section.findSymbolByName(symName)
|
|
629
|
+
if sym is not None:
|
|
630
|
+
yield MaybeFoundSymbolInfo(self, section, sym, 0)
|
|
631
|
+
|
|
528
632
|
def mixFolders(self) -> Segment:
|
|
529
633
|
newSegment = Segment(self.name, self.vram, self.size, self.vrom)
|
|
530
634
|
|
|
@@ -735,6 +839,7 @@ class MapFile:
|
|
|
735
839
|
symbol.vrom,
|
|
736
840
|
symbol.align,
|
|
737
841
|
symbol.nonmatchingSymExists,
|
|
842
|
+
symbol.isNonmatching,
|
|
738
843
|
symbol.inferredStatic,
|
|
739
844
|
)
|
|
740
845
|
|
|
@@ -768,6 +873,7 @@ class MapFile:
|
|
|
768
873
|
symbol.vrom,
|
|
769
874
|
symbol.align,
|
|
770
875
|
symbol.nonmatchingSymExists,
|
|
876
|
+
symbol.isNonmatching,
|
|
771
877
|
symbol.inferredStatic,
|
|
772
878
|
)
|
|
773
879
|
|
|
@@ -914,6 +1020,32 @@ class MapFile:
|
|
|
914
1020
|
possibleFiles.extend(possibleFilesAux)
|
|
915
1021
|
return None, possibleFiles
|
|
916
1022
|
|
|
1023
|
+
def findPossibleSymbolsByVram(
|
|
1024
|
+
self,
|
|
1025
|
+
address: int,
|
|
1026
|
+
) -> Generator[MaybeFoundSymbolInfo]:
|
|
1027
|
+
for segment in self._segmentsList:
|
|
1028
|
+
info = segment.findPossibleSymbolByVram(address)
|
|
1029
|
+
if info is not None:
|
|
1030
|
+
yield info
|
|
1031
|
+
|
|
1032
|
+
def findPossibleSymbolsByVrom(
|
|
1033
|
+
self,
|
|
1034
|
+
address: int,
|
|
1035
|
+
) -> Generator[MaybeFoundSymbolInfo]:
|
|
1036
|
+
for segment in self._segmentsList:
|
|
1037
|
+
info = segment.findPossibleSymbolByVrom(address)
|
|
1038
|
+
if info is not None:
|
|
1039
|
+
yield info
|
|
1040
|
+
|
|
1041
|
+
def findPossibleSymbolsByName(
|
|
1042
|
+
self,
|
|
1043
|
+
symName: str,
|
|
1044
|
+
) -> Generator[MaybeFoundSymbolInfo]:
|
|
1045
|
+
for segment in self._segmentsList:
|
|
1046
|
+
for info in segment.findPossibleSymbolsByName(symName):
|
|
1047
|
+
yield info
|
|
1048
|
+
|
|
917
1049
|
def findLowestDifferingSymbol(
|
|
918
1050
|
self, otherMapFile: MapFile
|
|
919
1051
|
) -> tuple[Symbol, Section, Symbol | None] | None:
|
|
@@ -71,6 +71,7 @@ class Symbol:
|
|
|
71
71
|
vrom: int | None
|
|
72
72
|
align: int | None
|
|
73
73
|
nonmatchingSymExists: bool
|
|
74
|
+
isNonmatching: bool
|
|
74
75
|
inferredStatic: bool
|
|
75
76
|
|
|
76
77
|
def __init__(
|
|
@@ -81,6 +82,7 @@ class Symbol:
|
|
|
81
82
|
vrom: int | None = None,
|
|
82
83
|
align: int | None = None,
|
|
83
84
|
nonmatchingSymExists: bool = False,
|
|
85
|
+
isNonmatching: bool = False,
|
|
84
86
|
inferredStatic: bool = False,
|
|
85
87
|
): ...
|
|
86
88
|
def getVramStr(self) -> str: ...
|
|
@@ -123,6 +125,8 @@ class Section:
|
|
|
123
125
|
) -> None: ...
|
|
124
126
|
@property
|
|
125
127
|
def isNoloadSection(self) -> bool: ...
|
|
128
|
+
def containsVram(self, address: int) -> bool: ...
|
|
129
|
+
def containsVrom(self, address: int) -> bool | None: ...
|
|
126
130
|
def serializeVram(self, humanReadable: bool = True) -> str | int | None: ...
|
|
127
131
|
def serializeSize(self, humanReadable: bool = True) -> str | int | None: ...
|
|
128
132
|
def serializeVrom(self, humanReadable: bool = True) -> str | int | None: ...
|
|
@@ -172,6 +176,8 @@ class Segment:
|
|
|
172
176
|
vrom: int | None,
|
|
173
177
|
align: int | None = None,
|
|
174
178
|
): ...
|
|
179
|
+
def containsVram(self, address: int) -> bool: ...
|
|
180
|
+
def containsVrom(self, address: int) -> bool | None: ...
|
|
175
181
|
def serializeVram(self, humanReadable: bool = True) -> str | int | None: ...
|
|
176
182
|
def serializeSize(self, humanReadable: bool = True) -> str | int | None: ...
|
|
177
183
|
def serializeVrom(self, humanReadable: bool = True) -> str | int | None: ...
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* SPDX-FileCopyrightText: © 2023-2025 Decompollaborate */
|
|
2
2
|
/* SPDX-License-Identifier: MIT */
|
|
3
3
|
|
|
4
|
-
use std::
|
|
4
|
+
use std::borrow::Cow;
|
|
5
5
|
|
|
6
6
|
use crate::{section, symbol};
|
|
7
7
|
|
|
@@ -32,31 +32,43 @@ impl<'a> FoundSymbolInfo<'a> {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
pub fn get_as_str(&self) -> String {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
35
|
+
self.get_as_str_impl(Cow::from(""))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
pub(crate) fn get_as_str_impl(&self, extra: Cow<'_, str>) -> String {
|
|
39
|
+
let name = &self.symbol.name;
|
|
40
|
+
let vram = self.symbol.get_vram_str();
|
|
41
|
+
let vrom = self.symbol.get_vrom_str();
|
|
42
|
+
let size = self.symbol.get_size_str();
|
|
43
|
+
let section_path = self.section.filepath.to_string_lossy();
|
|
44
|
+
|
|
45
|
+
format!("'{name}' (VRAM: {vram}, VROM: {vrom}, SIZE: {size}, {section_path}{extra})")
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
pub fn get_as_str_plus_offset(&self, sym_name: Option<String>) -> String {
|
|
46
|
-
|
|
49
|
+
self.get_as_str_plus_offset_impl(sym_name.map(Cow::from), Cow::from(""))
|
|
50
|
+
}
|
|
47
51
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
pub(crate) fn get_as_str_plus_offset_impl(
|
|
53
|
+
&self,
|
|
54
|
+
sym_name: Option<Cow<'_, str>>,
|
|
55
|
+
extra: Cow<'_, str>,
|
|
56
|
+
) -> String {
|
|
57
|
+
let message = if self.offset == 0 {
|
|
58
|
+
Cow::from("Symbol")
|
|
55
59
|
} else {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
let mes = if let Some(name) = sym_name {
|
|
61
|
+
name
|
|
62
|
+
} else {
|
|
63
|
+
Cow::from(format!(
|
|
64
|
+
"0x{0:X}",
|
|
65
|
+
self.symbol.vram.wrapping_add_signed(self.offset)
|
|
66
|
+
))
|
|
67
|
+
};
|
|
68
|
+
Cow::from(format!("{} is at 0x{:X} bytes inside", mes, self.offset))
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
format!("{0} {1}", message, self.get_as_str_impl(extra))
|
|
60
72
|
}
|
|
61
73
|
}
|
|
62
74
|
|