Skip to content

Commit b693e88

Browse files
authored
Merge pull request #131 from Decompollaborate/develop
1.16.2
2 parents a1fb34e + 2673201 commit b693e88

15 files changed

+140
-61
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[project]
55
name = "spimdisasm"
66
# Version should be synced with spimdisasm/__init__.py
7-
version = "1.16.0"
7+
version = "1.16.2"
88
description = "MIPS disassembler"
99
# license = "MIT"
1010
readme = "README.md"

spimdisasm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from __future__ import annotations
77

8-
__version_info__: tuple[int, int, int] = (1, 16, 0)
8+
__version_info__: tuple[int, int, int] = (1, 16, 2)
99
__version__ = ".".join(map(str, __version_info__))
1010
__author__ = "Decompollaborate"
1111

spimdisasm/common/ContextSymbols.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ def getLabelMacro(self) -> str|None:
519519
if self.isStatic():
520520
label += f"# static variable{GlobalConfig.LINE_ENDS}"
521521
if self.isAutogeneratedPad():
522-
label += f"# Automatically generated pad{GlobalConfig.LINE_ENDS}"
522+
label += f"# Automatically generated and unreferenced pad{GlobalConfig.LINE_ENDS}"
523523

524524
currentType = self.getTypeSpecial()
525525
if currentType == SymbolSpecialType.jumptablelabel:

spimdisasm/common/GlobalConfig.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,15 @@ def AGGRESSIVE_STRING_GUESSER(self, value: bool) -> None:
244244
PANIC_RANGE_CHECK: bool = False
245245
"""Produce a fatal error if a range check fails instead of just printing a warning"""
246246

247+
CREATE_DATA_PADS: bool = True
248+
"""Create dummy and unreferenced data symbols after another symbol which has non-zero user-declared size.
249+
250+
The generated pad symbols may have non-zero data"""
251+
CREATE_RODATA_PADS: bool = False
252+
"""Create dummy and unreferenced rodata symbols after another symbol which has non-zero user-declared size.
253+
254+
The generated pad symbols may have non-zero data"""
255+
247256
QUIET: bool = False
248257
VERBOSE: bool = False
249258

@@ -349,6 +358,9 @@ def addParametersToArgParse(self, parser: argparse.ArgumentParser):
349358

350359
miscConfig.add_argument("--panic-range-check", help=f"Produce a fatal error if a range check fails instead of just printing a warning. Defaults to {self.PANIC_RANGE_CHECK}", action=Utils.BooleanOptionalAction)
351360

361+
miscConfig.add_argument("--create-data-pads", help=f"Create dummy and unreferenced data symbols after another symbol which has non-zero user-declared size.\nThe generated pad symbols may have non-zero data. Defaults to {self.CREATE_DATA_PADS}", action=Utils.BooleanOptionalAction)
362+
miscConfig.add_argument("--create-rodata-pads", help=f"Create dummy and unreferenced rodata symbols after another symbol which has non-zero user-declared size.\nThe generated pad symbols may have non-zero data. Defaults to {self.CREATE_RODATA_PADS}", action=Utils.BooleanOptionalAction)
363+
352364

353365
verbosityConfig = parser.add_argument_group("Verbosity options")
354366

@@ -517,6 +529,11 @@ def parseArgs(self, args: argparse.Namespace):
517529
if args.panic_range_check is not None:
518530
self.PANIC_RANGE_CHECK = args.panic_range_check
519531

532+
if args.create_data_pads is not None:
533+
self.CREATE_DATA_PADS = args.create_data_pads
534+
if args.create_rodata_pads is not None:
535+
self.CREATE_RODATA_PADS = args.create_rodata_pads
536+
520537

521538
if args.verbose is not None:
522539
self.VERBOSE = args.verbose

spimdisasm/common/Relocation.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from .ContextSymbols import ContextSymbol
1212
from .FileSectionType import FileSectionType
1313
from .GlobalConfig import GlobalConfig
14+
from .GlobalConfig import Compiler
1415

1516

1617
class RelocType(enum.Enum):
@@ -149,7 +150,7 @@ class RelocationInfo:
149150
staticReference: RelocationStaticReference|None = None
150151
globalReloc: bool = False
151152

152-
def getName(self) -> str:
153+
def getName(self, isSplittedSymbol: bool=False) -> str:
153154
if isinstance(self.symbol, ContextSymbol):
154155
name = self.symbol.getName()
155156
else:
@@ -158,18 +159,27 @@ def getName(self) -> str:
158159
if self.addend == 0:
159160
return name
160161

161-
if self.relocType == RelocType.MIPS_LO16:
162-
if self.addend < -0x8000:
163-
return f"{name} - (0x{-self.addend:X} & 0xFFFF)"
164-
if self.addend > 0x7FFF:
165-
return f"{name} + (0x{self.addend:X} & 0xFFFF)"
162+
# IDO always compiles assembly using modern GAS, for both whole files
163+
# and splitted symbols. Using the workaround for addends outside the
164+
# range of an s16 has different behavior in modern GAS.
165+
if GlobalConfig.COMPILER == Compiler.IDO:
166+
if self.addend < 0:
167+
return f"{name} - 0x{-self.addend:X}"
168+
return f"{name} + 0x{self.addend:X}"
169+
170+
if isSplittedSymbol:
171+
if self.relocType == RelocType.MIPS_LO16:
172+
if self.addend < -0x8000:
173+
return f"{name} - (0x{-self.addend:X} & 0xFFFF)"
174+
if self.addend > 0x7FFF:
175+
return f"{name} + (0x{self.addend:X} & 0xFFFF)"
166176

167177
if self.addend < 0:
168178
return f"{name} - 0x{-self.addend:X}"
169179
return f"{name} + 0x{self.addend:X}"
170180

171-
def getNameWithReloc(self) -> str:
172-
name = self.getName()
181+
def getNameWithReloc(self, isSplittedSymbol: bool=False) -> str:
182+
name = self.getName(isSplittedSymbol=isSplittedSymbol)
173183

174184
percentRel = _percentRel.get(self.relocType)
175185
if percentRel is not None:
@@ -185,8 +195,8 @@ def getNameWithReloc(self) -> str:
185195

186196
return name
187197

188-
def getInlineStr(self) -> str:
189-
output = f" # {self.relocType.name} '{self.getName()}'"
198+
def getInlineStr(self, isSplittedSymbol: bool=False) -> str:
199+
output = f" # {self.relocType.name} '{self.getName(isSplittedSymbol=isSplittedSymbol)}'"
190200
if self.staticReference is not None:
191201
output += f" (static)"
192202
if self.globalReloc:

spimdisasm/common/Utils.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,15 +222,20 @@ def getMaybeBooleyFromMaybeStr(booley: str|None) -> bool|None:
222222
0x17,
223223
0x18,
224224
0x19,
225-
0x1A,
225+
# 0x1A, # Some games use this char as an escape sequence
226226
# 0x1B, # VT escape sequences
227227
0x1C,
228228
0x1D,
229229
0x1E,
230230
0x1F,
231231
}
232232

233-
escapeCharactersSpecialCases = {0x1B, 0x8C, 0x8D}
233+
escapeCharactersSpecialCases = {
234+
0x1A,
235+
0x1B,
236+
0x8C,
237+
0x8D,
238+
}
234239

235240
def decodeBytesToStrings(buf: bytes, offset: int, stringEncoding: str, terminator: int=0) -> tuple[list[str], int]:
236241
result = []

spimdisasm/elf32/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from .Elf32Rels import Elf32Rels as Elf32Rels
2929
from .Elf32Rels import Elf32RelEntry as Elf32RelEntry
3030

31-
from .Elf32File import Elf32File
31+
from .Elf32File import Elf32File as Elf32File
3232

3333
# To avoid breaking backwards compatibility
3434
from ..common.Relocation import RelocType as Elf32Relocs

spimdisasm/mips/FuncRodataEntry.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def writeToFile(self, f: TextIO, writeFunction: bool=True):
2929
# Write the rdata
3030
f.write(f".section .rodata{common.GlobalConfig.LINE_ENDS}")
3131
for sym in self.rodataSyms:
32-
f.write(sym.disassemble(migrate=True, useGlobalLabel=True))
32+
f.write(sym.disassemble(migrate=True, useGlobalLabel=True, isSplittedSymbol=True))
3333
f.write(common.GlobalConfig.LINE_ENDS)
3434

3535
if len(self.lateRodataSyms) > 0:
@@ -48,7 +48,7 @@ def writeToFile(self, f: TextIO, writeFunction: bool=True):
4848
align = 8
4949
f.write(f".late_rodata_alignment {align}{common.GlobalConfig.LINE_ENDS}")
5050
for sym in self.lateRodataSyms:
51-
f.write(sym.disassemble(migrate=True, useGlobalLabel=True))
51+
f.write(sym.disassemble(migrate=True, useGlobalLabel=True, isSplittedSymbol=True))
5252
f.write(common.GlobalConfig.LINE_ENDS)
5353

5454
if self.function is not None:
@@ -57,7 +57,7 @@ def writeToFile(self, f: TextIO, writeFunction: bool=True):
5757

5858
if writeFunction:
5959
# Write the function itself
60-
f.write(self.function.disassemble(migrate=self.hasRodataSyms()))
60+
f.write(self.function.disassemble(migrate=self.hasRodataSyms(), isSplittedSymbol=True))
6161

6262
@staticmethod
6363
def getEntryForFuncFromSection(func: symbols.SymbolFunction|None, rodataSection: sections.SectionRodata|None) -> FunctionRodataEntry:

spimdisasm/mips/MipsFileBase.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def disassemble(self, migrate: bool=False, useGlobalLabel: bool=True) -> str:
163163
output += self.getSpimdisasmVersionString()
164164

165165
for i, sym in enumerate(self.symbolList):
166-
output += sym.disassemble(useGlobalLabel=useGlobalLabel)
166+
output += sym.disassemble(migrate=migrate, useGlobalLabel=useGlobalLabel, isSplittedSymbol=False)
167167
if i + 1 < len(self.symbolList):
168168
output += common.GlobalConfig.LINE_ENDS
169169
return output

spimdisasm/mips/sections/MipsSectionData.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ def analyze(self):
3838
symbolList.append((localOffset, contextSym))
3939
contextSym.isMaybeString = self._stringGuesser(contextSym, localOffset)
4040
contextSym.isMaybePascalString = self._pascalStringGuesser(contextSym, localOffset)
41+
42+
if common.GlobalConfig.CREATE_DATA_PADS and contextSym.hasUserDeclaredSize():
43+
symDeclaredSize = contextSym.getSize()
44+
if symDeclaredSize > 0 and localOffset + symDeclaredSize < self.sizew * 4:
45+
# Try to respect the user-declared size for this symbol
46+
extraContextSym = self.addSymbol(contextSym.vram+symDeclaredSize, sectionType=self.sectionType, isAutogenerated=True, symbolVrom=currentVrom+symDeclaredSize)
47+
extraContextSym.isAutoCreatedPad = True
48+
4149
elif self.popPointerInDataReference(currentVram) is not None:
4250
contextSym = self.addSymbol(currentVram, sectionType=self.sectionType, isAutogenerated=True)
4351
contextSym.isMaybeString = self._stringGuesser(contextSym, localOffset)

spimdisasm/mips/sections/MipsSectionRodata.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,13 @@ def analyze(self):
101101
self.symbolsVRams.add(currentVram)
102102
symbolList.append((localOffset, currentVram))
103103

104+
if common.GlobalConfig.CREATE_RODATA_PADS and contextSym.hasUserDeclaredSize():
105+
symDeclaredSize = contextSym.getSize()
106+
if symDeclaredSize > 0 and localOffset + symDeclaredSize < self.sizew * 4:
107+
# Try to respect the user-declared size for this symbol
108+
extraContextSym = self.addSymbol(contextSym.vram+symDeclaredSize, sectionType=self.sectionType, isAutogenerated=True, symbolVrom=currentVrom+symDeclaredSize)
109+
extraContextSym.isAutoCreatedPad = True
110+
104111
localOffset += 4
105112

106113
previousSymbolWasLateRodata = False

0 commit comments

Comments
 (0)