Skip to content

Commit

Permalink
Merge pull request #134 from Decompollaborate/develop
Browse files Browse the repository at this point in the history
1.16.4
  • Loading branch information
AngheloAlf authored Aug 19, 2023
2 parents 4548f94 + 09ad568 commit 0fc5b6e
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 93 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[project]
name = "spimdisasm"
# Version should be synced with spimdisasm/__init__.py
version = "1.16.3"
version = "1.16.4"
description = "MIPS disassembler"
# license = "MIT"
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion spimdisasm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

__version_info__: tuple[int, int, int] = (1, 16, 3)
__version_info__: tuple[int, int, int] = (1, 16, 4)
__version__ = ".".join(map(str, __version_info__))
__author__ = "Decompollaborate"

Expand Down
11 changes: 9 additions & 2 deletions spimdisasm/common/ContextSymbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ class ContextSymbol:
allowedToReferenceConstants: bool = False
notAllowedToReferenceConstants: bool = False

isAutocreatedSymFromOtherSizedSym: bool = False


@property
def vram(self) -> int:
Expand Down Expand Up @@ -221,6 +223,9 @@ def isTrustableFunction(self, rsp: bool=False) -> bool:
if self.isGotLocal:
return False

if self.isAutocreatedSymFromOtherSizedSym:
return True

currentType = self.getTypeSpecial()

if GlobalConfig.TRUST_USER_FUNCTIONS and self.isUserDeclared:
Expand Down Expand Up @@ -566,7 +571,8 @@ def getCsvHeader() -> str:
output += "isDefined,isUserDeclared,isAutogenerated,isMaybeString,isMaybePascalString,"
output += "referenceCounter,overlayCategory,unknownSegment,"
output += "isGot,isGotGlobal,isGotLocal,gotIndex,"
output += "firstLoAccess,isAutogeneratedPad,isElfNotype"
output += "firstLoAccess,isAutogeneratedPad,isElfNotype,"
output += "isAutocreatedSymFromOtherSizedSym"
return output

def toCsv(self) -> str:
Expand All @@ -591,7 +597,8 @@ def toCsv(self) -> str:
output += f"{self.isDefined},{self.isUserDeclared},{self.isAutogenerated},{self.isMaybeString},{self.isMaybePascalString},"
output += f"{self.referenceCounter},{self.overlayCategory},{self.unknownSegment},"
output += f"{self.isGot},{self.isGotGlobal},{self.isGotLocal},{self.gotIndex},"
output += f"{self.firstLoAccess},{self.isAutogeneratedPad()},{self.isElfNotype}"
output += f"{self.firstLoAccess},{self.isAutogeneratedPad()},{self.isElfNotype},"
output += f"{self.isAutocreatedSymFromOtherSizedSym}"
return output


Expand Down
11 changes: 7 additions & 4 deletions spimdisasm/common/GlobalConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,12 @@ def fromStr(value: str) -> Compiler:


class Abi(enum.Enum):
O32 = "O32"
N32 = "N32"
N64 = "N64"
O32 = "O32"
N32 = "N32"
O64 = "O64"
N64 = "N64"
EABI32 = "EABI32"
EABI64 = "EABI64"

@staticmethod
def fromStr(value: str) -> Abi:
Expand Down Expand Up @@ -311,7 +314,7 @@ def addParametersToArgParse(self, parser: argparse.ArgumentParser):

backendConfig.add_argument("--endian", help=f"Set the endianness of input files. Defaults to {self.ENDIAN.name.lower()}", choices=["big", "little", "middle"], default=self.ENDIAN.name.lower())

backendConfig.add_argument("--abi", help=f"Changes the ABI of the disassembly, applying corresponding tweaks. Defaults to {self.ABI.name}", choices=["O32", "N32", "N64"], default=self.ABI.name)
backendConfig.add_argument("--abi", help=f"Changes the ABI of the disassembly, applying corresponding tweaks. Defaults to {self.ABI.name}", choices=["O32", "N32", "O64", "N64", "EABI32", "EABI64"], default=self.ABI.name)
backendConfig.add_argument("--arch-level", help=f"Changes the arch level of the disassembly, applying corresponding tweaks. Defaults to {self.ARCHLEVEL.name}", choices=archLevelOptions, default=self.ARCHLEVEL.name)


Expand Down
83 changes: 83 additions & 0 deletions spimdisasm/elf32/Elf32Constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,41 @@ class Elf32HeaderFlag(enum.Enum):
FP64 = 0x00000200 # Uses FP64 (12 callee-saved).
NAN2008 = 0x00000400 # Uses IEEE 754-2008 NaN encoding.


# ABI
O32 = 0x00001000 # The original o32 abi.
O64 = 0x00002000 # O32 extended to work on 64 bit architectures
EABI32 = 0x00003000 # EABI in 32 bit mode
EABI64 = 0x00004000 # EABI in 64 bit mode


# CPU
CPU = 0x00FF0000

_3900 = 0x00810000
_4010 = 0x00820000
_4100 = 0x00830000
_4650 = 0x00850000
_4120 = 0x00870000
_4111 = 0x00880000
SB1 = 0x008a0000
OCTEON = 0x008b0000
XLR = 0x008c0000
OCTEON2 = 0x008d0000
OCTEON3 = 0x008e0000
_5400 = 0x00910000
_5900 = 0x00920000
IAMR2 = 0x00930000
_5500 = 0x00980000
_9000 = 0x00990000
LS2E = 0x00A00000
LS2F = 0x00A10000
GS464 = 0x00A20000
GS464E = 0x00A30000
GS264E = 0x00A40000


# arch level
ARCH = 0xF0000000 # MIPS architecture level.

# Legal values for MIPS architecture level
Expand All @@ -95,6 +130,7 @@ def parseFlags(rawFlags: int) -> tuple[list[Elf32HeaderFlag], int]:
Elf32HeaderFlag.XGOT, Elf32HeaderFlag.F_64BIT_WHIRL, Elf32HeaderFlag.ABI2,
Elf32HeaderFlag.ABI_ON32,
Elf32HeaderFlag._32BITSMODE, Elf32HeaderFlag.FP64, Elf32HeaderFlag.NAN2008,
Elf32HeaderFlag.O32, Elf32HeaderFlag.O64, Elf32HeaderFlag.EABI32, Elf32HeaderFlag.EABI64
]
parsedFlags: list[Elf32HeaderFlag] = list()

Expand All @@ -103,6 +139,53 @@ def parseFlags(rawFlags: int) -> tuple[list[Elf32HeaderFlag], int]:
parsedFlags.append(flagEnum)
rawFlags &= ~flagEnum.value

cpu = rawFlags & Elf32HeaderFlag.CPU.value
rawFlags &= ~Elf32HeaderFlag.CPU.value
if cpu == Elf32HeaderFlag._3900.value:
parsedFlags.append(Elf32HeaderFlag._3900)
elif cpu == Elf32HeaderFlag._4010.value:
parsedFlags.append(Elf32HeaderFlag._4010)
elif cpu == Elf32HeaderFlag._4100.value:
parsedFlags.append(Elf32HeaderFlag._4100)
elif cpu == Elf32HeaderFlag._4650.value:
parsedFlags.append(Elf32HeaderFlag._4650)
elif cpu == Elf32HeaderFlag._4120.value:
parsedFlags.append(Elf32HeaderFlag._4120)
elif cpu == Elf32HeaderFlag._4111.value:
parsedFlags.append(Elf32HeaderFlag._4111)
elif cpu == Elf32HeaderFlag.SB1.value:
parsedFlags.append(Elf32HeaderFlag.SB1)
elif cpu == Elf32HeaderFlag.OCTEON.value:
parsedFlags.append(Elf32HeaderFlag.OCTEON)
elif cpu == Elf32HeaderFlag.XLR.value:
parsedFlags.append(Elf32HeaderFlag.XLR)
elif cpu == Elf32HeaderFlag.OCTEON2.value:
parsedFlags.append(Elf32HeaderFlag.OCTEON2)
elif cpu == Elf32HeaderFlag.OCTEON3.value:
parsedFlags.append(Elf32HeaderFlag.OCTEON3)
elif cpu == Elf32HeaderFlag._5400.value:
parsedFlags.append(Elf32HeaderFlag._5400)
elif cpu == Elf32HeaderFlag._5900.value:
parsedFlags.append(Elf32HeaderFlag._5900)
elif cpu == Elf32HeaderFlag.IAMR2.value:
parsedFlags.append(Elf32HeaderFlag.IAMR2)
elif cpu == Elf32HeaderFlag._5500.value:
parsedFlags.append(Elf32HeaderFlag._5500)
elif cpu == Elf32HeaderFlag._9000.value:
parsedFlags.append(Elf32HeaderFlag._9000)
elif cpu == Elf32HeaderFlag.LS2E.value:
parsedFlags.append(Elf32HeaderFlag.LS2E)
elif cpu == Elf32HeaderFlag.LS2F.value:
parsedFlags.append(Elf32HeaderFlag.LS2F)
elif cpu == Elf32HeaderFlag.GS464.value:
parsedFlags.append(Elf32HeaderFlag.GS464)
elif cpu == Elf32HeaderFlag.GS464E.value:
parsedFlags.append(Elf32HeaderFlag.GS464E)
elif cpu == Elf32HeaderFlag.GS264E.value:
parsedFlags.append(Elf32HeaderFlag.GS264E)
else:
rawFlags |= cpu

archLevel = rawFlags & Elf32HeaderFlag.ARCH.value
rawFlags &= ~Elf32HeaderFlag.ARCH.value
if archLevel == Elf32HeaderFlag.ARCH_1.value:
Expand Down
16 changes: 15 additions & 1 deletion spimdisasm/elf32/Elf32File.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,23 @@ def handleFlags(self) -> None:
common.Utils.eprint(f"Warning: Elf with NAN2008 flag.")
common.Utils.eprint(f"\t This flag is currently not handled in any way, please report this")

if Elf32HeaderFlag.ABI2 in self.elfFlags:
if Elf32HeaderFlag.ABI2 in self.elfFlags and Elf32HeaderFlag.O64 in self.elfFlags:
common.Utils.eprint(f"Warning: Elf compiled using N64 ABI. Support is in experimental state")
common.GlobalConfig.ABI = common.Abi.N32
elif Elf32HeaderFlag.ABI2 in self.elfFlags:
common.Utils.eprint(f"Warning: Elf compiled using N32 ABI. Support is in experimental state")
common.GlobalConfig.ABI = common.Abi.N32
elif Elf32HeaderFlag.O64 in self.elfFlags:
common.Utils.eprint(f"Warning: Elf compiled using O64 ABI. Support is in experimental state")
common.GlobalConfig.ABI = common.Abi.O64

if Elf32HeaderFlag.EABI32 in self.elfFlags:
common.Utils.eprint(f"Warning: Elf compiled using EABI32 ABI. Support is in experimental state")
common.GlobalConfig.ABI = common.Abi.EABI32

if Elf32HeaderFlag.EABI64 in self.elfFlags:
common.Utils.eprint(f"Warning: Elf compiled using EABI64 ABI. Support is in experimental state")
common.GlobalConfig.ABI = common.Abi.N32

unkArchLevel = {Elf32HeaderFlag.ARCH_5, Elf32HeaderFlag.ARCH_32, Elf32HeaderFlag.ARCH_64, Elf32HeaderFlag.ARCH_32R2, Elf32HeaderFlag.ARCH_64R2} & set(self.elfFlags)
if unkArchLevel:
Expand Down
20 changes: 15 additions & 5 deletions spimdisasm/elfObjDisasm/ElfObjDisasmInternals.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import argparse
from pathlib import Path
import rabbitizer

from .. import common
from .. import elf32
Expand Down Expand Up @@ -246,7 +247,9 @@ def addContextSymFromSymEntry(context: common.Context, symEntry: elf32.Elf32SymE
contextSym = segment.addSymbol(symAddress, vromAddress=symVrom)
contextSym.isElfNotype = True
else:
common.Utils.eprint(f"Warning: NOTYPE symbol '{symName}' has an unhandled shndx value: '0x{symEntry.shndx:X}'")
bind = elf32.Elf32SymbolTableBinding.fromValue(symEntry.stBind)
if bind != elf32.Elf32SymbolTableBinding.LOCAL:
common.Utils.eprint(f"Warning: Non-LOCAL ({bind}) NOTYPE symbol '{symName}' has an unhandled shndx value: '0x{symEntry.shndx:X}'")
contextSym = segment.addSymbol(symAddress, vromAddress=symVrom)
else:
common.Utils.eprint(f"Warning: symbol '{symName}' has an unhandled stType: '{symEntry.stType}'")
Expand Down Expand Up @@ -358,11 +361,13 @@ def injectAllElfSymbols(context: common.Context, elfFile: elf32.Elf32File, proce
return

def processGlobalOffsetTable(context: common.Context, elfFile: elf32.Elf32File) -> None:
if elfFile.dynamic is not None and elfFile.got is not None:
if elfFile.dynamic is not None:
common.GlobalConfig.GP_VALUE = elfFile.dynamic.getGpValue()
if elfFile.reginfo is not None:
common.GlobalConfig.GP_VALUE = elfFile.reginfo.gpValue

if elfFile.reginfo is not None:
common.GlobalConfig.GP_VALUE = elfFile.reginfo.gpValue

if elfFile.dynamic is not None and elfFile.got is not None:
globalsTable = [gotEntry.getAddress() for gotEntry in elfFile.got.globalsTable]

assert elfFile.dynamic.pltGot is not None
Expand Down Expand Up @@ -390,6 +395,11 @@ def processArguments(args: argparse.Namespace) -> int:
elfFile.handleHeaderIdent()
elfFile.handleFlags()

instrCategory = args.instr_category
if instrCategory is None:
if elf32.Elf32Constants.Elf32HeaderFlag._5900 in elfFile.elfFlags:
instrCategory = "r5900"

common.Utils.printQuietless(f"{PROGNAME} {inputPath}: Processing global offset table...")
processGlobalOffsetTable(context, elfFile)

Expand Down Expand Up @@ -423,7 +433,7 @@ def processArguments(args: argparse.Namespace) -> int:

changeGlobalSegmentRanges(context, processedSegments)

fec.FrontendUtilities.configureProcessedFiles(processedSegments, args.instr_category)
fec.FrontendUtilities.configureProcessedFiles(processedSegments, instrCategory)

common.Utils.printQuietless(f"{PROGNAME} {inputPath}: Injecting elf symbols...")
injectAllElfSymbols(context, elfFile, processedSegments, sectionsPerName)
Expand Down
2 changes: 1 addition & 1 deletion spimdisasm/frontendCommon/FrontendUtilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def getInstrCategoryFromStr(category: str|None) -> rabbitizer.Enum:
return gInstrCategoriesNameMap.get(category.lower(), rabbitizer.InstrCategory.CPU)


def configureProcessedFiles(processedFiles: dict[common.FileSectionType, list[mips.sections.SectionBase]], category: str) -> None:
def configureProcessedFiles(processedFiles: dict[common.FileSectionType, list[mips.sections.SectionBase]], category: str|None) -> None:
instrCat = getInstrCategoryFromStr(category)

for textFile in processedFiles.get(common.FileSectionType.Text, []):
Expand Down
Loading

0 comments on commit 0fc5b6e

Please sign in to comment.