From 9f2a6aa00bccb125855a84e334903026b7623ad7 Mon Sep 17 00:00:00 2001 From: Anghelo Carvajal Date: Wed, 12 Feb 2025 09:08:28 -0300 Subject: [PATCH 1/3] Fix to avoid incorrectly inferring the symbol's type if the given symbol is referenced on complex control flows. --- CHANGELOG.md | 5 +++++ pyproject.toml | 2 +- spimdisasm/__init__.py | 4 ++-- spimdisasm/mips/symbols/MipsSymbolFunction.py | 12 ++++++------ 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcf1fca0..705ffb76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Fix to avoid incorrectly inferring the symbol's type if the given symbol is + referenced on complex control flows. + ## [1.32.1] - 2025-02-02 ### Changed diff --git a/pyproject.toml b/pyproject.toml index 06ea9619..f514c30e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ [project] name = "spimdisasm" # Version should be synced with spimdisasm/__init__.py -version = "1.32.1" +version = "1.32.2" description = "MIPS disassembler" readme = "README.md" license = {file = "LICENSE"} diff --git a/spimdisasm/__init__.py b/spimdisasm/__init__.py index 75bf9ad3..8288dbfc 100644 --- a/spimdisasm/__init__.py +++ b/spimdisasm/__init__.py @@ -5,8 +5,8 @@ from __future__ import annotations -__version_info__: tuple[int, int, int] = (1, 32, 1) -__version__ = ".".join(map(str, __version_info__))# + "-dev0" +__version_info__: tuple[int, int, int] = (1, 32, 2) +__version__ = ".".join(map(str, __version_info__)) + "-dev0" __author__ = "Decompollaborate" from . import common as common diff --git a/spimdisasm/mips/symbols/MipsSymbolFunction.py b/spimdisasm/mips/symbols/MipsSymbolFunction.py index 381bfdc3..700c4c44 100644 --- a/spimdisasm/mips/symbols/MipsSymbolFunction.py +++ b/spimdisasm/mips/symbols/MipsSymbolFunction.py @@ -19,7 +19,7 @@ def __init__(self, context: common.Context, vromStart: int, vromEnd: int, inFile self.instrAnalyzer = analysis.InstrAnalyzer(self.vram, context) - self.branchesTaken: set[int] = set() + self.branchesTaken: set[tuple[int, bool]] = set() self.pointersOffsets: set[int] = set() self.pointersRemoved: bool = False @@ -40,7 +40,7 @@ def sizew(self) -> int: def isFunction(self) -> bool: return True - def _lookAheadSymbolFinder(self, instr: rabbitizer.Instruction, prevInstr: rabbitizer.Instruction, instructionOffset: int, trackedRegistersOriginal: rabbitizer.RegistersTracker) -> None: + def _lookAheadSymbolFinder(self, instr: rabbitizer.Instruction, prevInstr: rabbitizer.Instruction, instructionOffset: int, trackedRegistersOriginal: rabbitizer.RegistersTracker, prev_is_likely: bool) -> None: if not prevInstr.isBranch() and not prevInstr.isUnconditionalBranch(): return @@ -58,9 +58,9 @@ def _lookAheadSymbolFinder(self, instr: rabbitizer.Instruction, prevInstr: rabbi self.instrAnalyzer.processInstr(regsTracker, instr, instructionOffset, currentVram, None) - if instructionOffset in self.branchesTaken: + if (instructionOffset, prev_is_likely) in self.branchesTaken: return - self.branchesTaken.add(instructionOffset) + self.branchesTaken.add((instructionOffset, prev_is_likely)) sizew = len(self.instructions)*4 while branch < sizew: @@ -69,7 +69,7 @@ def _lookAheadSymbolFinder(self, instr: rabbitizer.Instruction, prevInstr: rabbi self.instrAnalyzer.processInstr(regsTracker, targetInstr, branch, self.getVramOffset(branch), prevTargetInstr) - self._lookAheadSymbolFinder(targetInstr, prevTargetInstr, branch, regsTracker) + self._lookAheadSymbolFinder(targetInstr, prevTargetInstr, branch, regsTracker, prev_is_likely or prevTargetInstr.isBranchLikely()) if prevTargetInstr.isUnconditionalBranch(): # Since we took the branch on the previous _lookAheadSymbolFinder @@ -129,7 +129,7 @@ def _runInstructionAnalyzer(self) -> None: self.instrAnalyzer.processInstr(regsTracker, instr, instructionOffset, currentVram, prevInstr) # look-ahead symbol finder - self._lookAheadSymbolFinder(instr, prevInstr, instructionOffset, regsTracker) + self._lookAheadSymbolFinder(instr, prevInstr, instructionOffset, regsTracker, prevInstr.isBranchLikely()) if prevInstr.isJumpWithAddress() and not prevInstr.doesLink(): targetVram = prevInstr.getBranchVramGeneric() From 57674ef0e38a1997cb4a5347ca9bb5d1d501a654 Mon Sep 17 00:00:00 2001 From: Anghelo Carvajal Date: Wed, 12 Feb 2025 11:24:40 -0300 Subject: [PATCH 2/3] Avoid symbolizing $gp accesses if the current function set that register to a different value --- CHANGELOG.md | 2 ++ spimdisasm/mips/symbols/MipsSymbolFunction.py | 2 ++ .../mips/symbols/analysis/InstrAnalyzer.py | 22 ++++++++++++++----- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 705ffb76..976735a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix to avoid incorrectly inferring the symbol's type if the given symbol is referenced on complex control flows. +- Avoid symbolizing $gp accesses if the current function set that register to a + different value. ## [1.32.1] - 2025-02-02 diff --git a/spimdisasm/mips/symbols/MipsSymbolFunction.py b/spimdisasm/mips/symbols/MipsSymbolFunction.py index 700c4c44..35351f86 100644 --- a/spimdisasm/mips/symbols/MipsSymbolFunction.py +++ b/spimdisasm/mips/symbols/MipsSymbolFunction.py @@ -380,6 +380,8 @@ def _generateRelocsFromInstructionAnalyzer(self) -> None: self.relocs[instrOffset] = common.RelocationInfo(relocType, "_gp_disp") for instrOffset, gpInfo in self.instrAnalyzer.gpSets.items(): + if gpInfo is None: + continue hiInstrOffset = gpInfo.hiOffset hiInstr = self.instructions[hiInstrOffset//4] instr = self.instructions[instrOffset//4] diff --git a/spimdisasm/mips/symbols/analysis/InstrAnalyzer.py b/spimdisasm/mips/symbols/analysis/InstrAnalyzer.py index 7b845b4c..a5b0f07d 100644 --- a/spimdisasm/mips/symbols/analysis/InstrAnalyzer.py +++ b/spimdisasm/mips/symbols/analysis/InstrAnalyzer.py @@ -48,6 +48,8 @@ def __init__(self, funcVram: int, context: common.Context) -> None: self.context = context "read-only" + self.currentGpValue: int|None = common.GlobalConfig.GP_VALUE + self.referencedVrams: set[int] = set() "Every referenced vram found" self.referencedConstants: set[int] = set() @@ -124,7 +126,7 @@ def __init__(self, funcVram: int, context: common.Context) -> None: self.gpSetsOffsets: set[int] = set() "Offsets of every instruction that set the $gp register" - self.gpSets: dict[int, GpSetInfo] = dict() + self.gpSets: dict[int, GpSetInfo|None] = dict() "Instructions setting the $gp register, key: offset of the low instruction" @@ -233,15 +235,15 @@ def pairHiLo(self, hiValue: int|None, luiOffset: int|None, lowerInstr: rabbitize else: return self.symbolLoInstrOffset[lowerOffset] - if hiValue is None and common.GlobalConfig.GP_VALUE is None: + if hiValue is None and self.currentGpValue is None: # Trying to pair a gp relative offset, but we don't know the gp address return None if hiValue is not None: upperHalf = hiValue else: - assert common.GlobalConfig.GP_VALUE is not None - upperHalf = common.GlobalConfig.GP_VALUE + assert self.currentGpValue is not None + upperHalf = self.currentGpValue return upperHalf + lowerHalf @@ -393,9 +395,12 @@ def symbolFinder(self, regsTracker: rabbitizer.RegistersTracker, instr: rabbitiz else: hiGpValue = luiInstr.getProcessedImmediate() << 16 loGpValue = instr.getProcessedImmediate() - self.gpSets[instrOffset] = GpSetInfo(luiOffset, instrOffset, hiGpValue+loGpValue) + gpValue = hiGpValue+loGpValue + self.gpSets[instrOffset] = GpSetInfo(luiOffset, instrOffset, gpValue) self.gpSetsOffsets.add(luiOffset) self.gpSetsOffsets.add(instrOffset) + if not common.GlobalConfig.PIC: + self.currentGpValue = gpValue # early return to avoid counting this pairing as a normal symbol return @@ -484,6 +489,13 @@ def processInstr(self, regsTracker: rabbitizer.RegistersTracker, instr: rabbitiz self.cploads[instrOffset] = cpload regsTracker.overwriteRegisters(instr, instrOffset) + if not common.GlobalConfig.PIC: + dstReg = instr.getDestinationGpr() + if dstReg is not None and (dstReg == rabbitizer.RegGprO32.gp or dstReg == rabbitizer.RegGprN32.gp): + if instrOffset not in self.gpSets: + self.gpSets[instrOffset] = None + self.gpSetsOffsets.add(instrOffset) + self.currentGpValue = None def processPrevFuncCall(self, regsTracker: rabbitizer.RegistersTracker, instr: rabbitizer.Instruction, prevInstr: rabbitizer.Instruction, currentVram: int | None = None) -> None: From 593bffc2f9d308e9a19ad3e4611d42ca464ff24d Mon Sep 17 00:00:00 2001 From: Anghelo Carvajal Date: Wed, 12 Feb 2025 11:26:30 -0300 Subject: [PATCH 3/3] version bump --- CHANGELOG.md | 3 +++ README.md | 2 +- spimdisasm/__init__.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 976735a7..f24569ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.32.2] - 2025-02-12 + ### Fixed - Fix to avoid incorrectly inferring the symbol's type if the given symbol is @@ -1749,6 +1751,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Version 1.0.0 [unreleased]: https://github.com/Decompollaborate/spimdisasm/compare/master...develop +[1.32.2]: https://github.com/Decompollaborate/spimdisasm/compare/1.32.1...1.32.2 [1.32.1]: https://github.com/Decompollaborate/spimdisasm/compare/1.32.0...1.32.1 [1.32.0]: https://github.com/Decompollaborate/spimdisasm/compare/1.31.3...1.32.0 [1.31.3]: https://github.com/Decompollaborate/spimdisasm/compare/1.31.2...1.31.3 diff --git a/README.md b/README.md index 3ff9333f..73c5624b 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ If you use a `requirements.txt` file in your repository, then you can add this library with the following line: ```txt -spimdisasm>=1.32.1,<2.0.0 +spimdisasm>=1.32.2,<2.0.0 ``` ### Development version diff --git a/spimdisasm/__init__.py b/spimdisasm/__init__.py index 8288dbfc..5631f59a 100644 --- a/spimdisasm/__init__.py +++ b/spimdisasm/__init__.py @@ -6,7 +6,7 @@ from __future__ import annotations __version_info__: tuple[int, int, int] = (1, 32, 2) -__version__ = ".".join(map(str, __version_info__)) + "-dev0" +__version__ = ".".join(map(str, __version_info__))# + "-dev0" __author__ = "Decompollaborate" from . import common as common