Skip to content

Commit 7c67bb9

Browse files
authored
Merge pull request #118 from Decompollaborate/develop
1.13.2
2 parents 1b9c4cb + 11c9e64 commit 7c67bb9

File tree

10 files changed

+171
-55
lines changed

10 files changed

+171
-55
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.13.1"
7+
version = "1.13.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__ = (1, 13, 1)
8+
__version_info__ = (1, 13, 2)
99
__version__ = ".".join(map(str, __version_info__))
1010
__author__ = "Decompollaborate"
1111

spimdisasm/common/FileSectionType.py

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python3
22

3-
# SPDX-FileCopyrightText: © 2022 Decompollaborate
3+
# SPDX-FileCopyrightText: © 2022-2023 Decompollaborate
44
# SPDX-License-Identifier: MIT
55

66
from __future__ import annotations
@@ -9,6 +9,8 @@
99

1010

1111
class FileSectionType(OrderedEnum):
12+
Dummy = -4
13+
End = -3
1214
Unknown = -2
1315
Invalid = -1
1416

@@ -20,33 +22,14 @@ class FileSectionType(OrderedEnum):
2022

2123
@staticmethod
2224
def fromId(sectionId: int) -> FileSectionType:
23-
if sectionId == 1:
24-
return FileSectionType.Text
25-
if sectionId == 2:
26-
return FileSectionType.Data
27-
if sectionId == 3:
28-
return FileSectionType.Rodata
29-
if sectionId == 4:
30-
return FileSectionType.Bss
31-
if sectionId == 5:
32-
return FileSectionType.Reloc
33-
return FileSectionType.Invalid
25+
try:
26+
return FileSectionType(sectionId)
27+
except:
28+
return FileSectionType.Invalid
3429

3530
@staticmethod
3631
def fromStr(x: str) -> FileSectionType:
37-
if x == ".text":
38-
return FileSectionType.Text
39-
if x == ".data":
40-
return FileSectionType.Data
41-
if x == ".rodata":
42-
return FileSectionType.Rodata
43-
if x == ".rdata":
44-
return FileSectionType.Rodata
45-
if x == ".bss":
46-
return FileSectionType.Bss
47-
if x == ".reloc":
48-
return FileSectionType.Reloc
49-
return FileSectionType.Invalid
32+
return gNameToSectionType.get(x, FileSectionType.Invalid)
5033

5134
def toStr(self) -> str:
5235
if self == FileSectionType.Text:
@@ -87,6 +70,17 @@ def toSectionName(self) -> str:
8770
return ".ovl"
8871
return ""
8972

73+
gNameToSectionType = {
74+
".text": FileSectionType.Text,
75+
".data": FileSectionType.Data,
76+
".rodata": FileSectionType.Rodata,
77+
".rdata": FileSectionType.Rodata,
78+
".bss": FileSectionType.Bss,
79+
".reloc": FileSectionType.Reloc,
80+
".end": FileSectionType.End,
81+
".dummy": FileSectionType.Dummy,
82+
}
83+
9084

9185
FileSections_ListBasic = [FileSectionType.Text, FileSectionType.Data, FileSectionType.Rodata, FileSectionType.Bss]
9286
FileSections_ListAll = [FileSectionType.Text, FileSectionType.Data, FileSectionType.Rodata, FileSectionType.Bss, FileSectionType.Reloc]

spimdisasm/common/FileSplitFormat.py

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,13 @@ def __iter__(self):
4848
isRsp = True
4949
offsetStr = offsetStr[:-1]
5050

51-
if fileName == ".text":
52-
section = FileSectionType.Text
53-
continue
54-
elif fileName == ".data":
55-
section = FileSectionType.Data
56-
continue
57-
elif fileName == ".rodata":
58-
section = FileSectionType.Rodata
59-
continue
60-
elif fileName == ".rdata":
61-
section = FileSectionType.Rodata
62-
continue
63-
elif fileName == ".bss":
64-
section = FileSectionType.Bss
65-
continue
66-
elif fileName == ".end":
67-
break
51+
possibleSection = FileSectionType.fromStr(fileName)
52+
if possibleSection != FileSectionType.Invalid:
53+
if possibleSection == FileSectionType.End:
54+
break
55+
else:
56+
section = possibleSection
57+
continue
6858

6959
vram = int(vramStr, 16)
7060
offset = int(offsetStr, 16)

spimdisasm/elf32/Elf32Constants.py

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@
1212
class Elf32HeaderIdentifier:
1313
@enum.unique
1414
class FileClass(enum.Enum):
15-
# EI_CLASS 4 /* File class byte index */
15+
# EI_CLASS 4 # File class byte index
1616
CLASSNONE = 0 # Invalid class
1717
CLASS32 = 1 # 32-bit objects
1818
CLASS64 = 2 # 64-bit objects
1919
CLASSNUM = 3
2020

2121
@enum.unique
2222
class DataEncoding(enum.Enum):
23-
# EI_DATA 5 /* Data encoding byte index */
23+
# EI_DATA 5 # Data encoding byte index
2424
DATANONE = 0 # Invalid data encoding
2525
DATA2LSB = 1 # 2's complement, little endian
2626
DATA2MSB = 2 # 2's complement, big endian
2727
DATANUM = 3 #
2828

2929
class OsAbi(enum.Enum):
30-
# EI_OSABI 7 /* OS ABI identification */
30+
# EI_OSABI 7 # OS ABI identification
3131
NONE = 0 # UNIX System V ABI
3232
SYSV = 0 # Alias.
3333
HPUX = 1 # HP-UX
@@ -54,10 +54,10 @@ class Elf32ObjectFileType(enum.Enum):
5454
DYN = 3 # Shared object file
5555
CORE = 4 # Core file
5656
NUM = 5 # Number of defined types
57-
# LOOS 0xfe00 /* OS-specific range start */
58-
# HIOS 0xfeff /* OS-specific range end */
59-
# LOPROC 0xff00 /* Processor-specific range start */
60-
# HIPROC 0xffff /* Processor-specific range end */
57+
# LOOS 0xfe00 # OS-specific range start
58+
# HIOS 0xfeff # OS-specific range end
59+
# LOPROC 0xff00 # Processor-specific range start
60+
# HIPROC 0xffff # Processor-specific range end
6161

6262

6363
# Legal values for e_flags field of Elf32_Ehdr
@@ -90,11 +90,12 @@ class Elf32HeaderFlag(enum.Enum):
9090

9191
@staticmethod
9292
def parseFlags(rawFlags: int) -> tuple[list[Elf32HeaderFlag], int]:
93-
flagsToCheck = {
93+
flagsToCheck = [
9494
Elf32HeaderFlag.NOREORDER, Elf32HeaderFlag.PIC, Elf32HeaderFlag.CPIC,
9595
Elf32HeaderFlag.XGOT, Elf32HeaderFlag.F_64BIT_WHIRL, Elf32HeaderFlag.ABI2,
9696
Elf32HeaderFlag.ABI_ON32,
97-
Elf32HeaderFlag._32BITSMODE, Elf32HeaderFlag.FP64, Elf32HeaderFlag.NAN2008}
97+
Elf32HeaderFlag._32BITSMODE, Elf32HeaderFlag.FP64, Elf32HeaderFlag.NAN2008,
98+
]
9899
parsedFlags: list[Elf32HeaderFlag] = list()
99100

100101
for flagEnum in flagsToCheck:
@@ -145,13 +146,68 @@ class Elf32SectionHeaderType(enum.Enum):
145146

146147
MIPS_LIBLIST = 0x70000000
147148
MIPS_MSYM = 0x70000001
149+
MIPS_CONFLICT = 0x70000002
148150
MIPS_GPTAB = 0x70000003
149151
MIPS_DEBUG = 0x70000005
150152
MIPS_REGINFO = 0x70000006
151153
MIPS_OPTIONS = 0x7000000D
152154
MIPS_SYMBOL_LIB = 0x70000020
153155
MIPS_ABIFLAGS = 0x7000002A
154156

157+
@staticmethod
158+
def fromValue(value: int) -> Elf32SectionHeaderType|None:
159+
try:
160+
return Elf32SectionHeaderType(value)
161+
except ValueError:
162+
return None
163+
164+
# Values for section header, sh_flags field.
165+
@enum.unique
166+
class Elf32SectionHeaderFlag(enum.Enum):
167+
WRITE = 0x00000001 # Writable data during execution
168+
ALLOC = 0x00000002 # Occupies memory during execution
169+
EXECINSTR = 0x00000004 # Executable machine instructions
170+
MERGE = 0x00000010 # Data in this section can be merged
171+
STRINGS = 0x00000020 # Contains null terminated character strings
172+
INFO_LINK = 0x00000040 # sh_info holds section header table index
173+
LINK_ORDER = 0x00000080 # Preserve section ordering when linking
174+
OS_NONCONFORMING = 0x00000100 # OS specific processing required
175+
GROUP = 0x00000200 # Member of a section group
176+
TLS = 0x00000400 # Thread local storage section
177+
COMPRESSED = 0x00000800 # Section with compressed data
178+
179+
EXCLUDE = 0x80000000 # Link editor is to exclude
180+
# this section from executable
181+
# and shared library that it
182+
# builds when those objects
183+
# are not to be further
184+
# relocated.
185+
186+
@staticmethod
187+
def parseFlags(rawFlags: int) -> tuple[list[Elf32SectionHeaderFlag], int]:
188+
flagsToCheck = [
189+
Elf32SectionHeaderFlag.WRITE,
190+
Elf32SectionHeaderFlag.ALLOC,
191+
Elf32SectionHeaderFlag.EXECINSTR,
192+
Elf32SectionHeaderFlag.MERGE,
193+
Elf32SectionHeaderFlag.STRINGS,
194+
Elf32SectionHeaderFlag.INFO_LINK,
195+
Elf32SectionHeaderFlag.LINK_ORDER,
196+
Elf32SectionHeaderFlag.OS_NONCONFORMING,
197+
Elf32SectionHeaderFlag.GROUP,
198+
Elf32SectionHeaderFlag.TLS,
199+
Elf32SectionHeaderFlag.COMPRESSED,
200+
Elf32SectionHeaderFlag.EXCLUDE,
201+
]
202+
parsedFlags: list[Elf32SectionHeaderFlag] = list()
203+
204+
for flagEnum in flagsToCheck:
205+
if rawFlags & flagEnum.value:
206+
parsedFlags.append(flagEnum)
207+
rawFlags &= ~flagEnum.value
208+
209+
return parsedFlags, rawFlags
210+
155211

156212
# a.k.a. STT (symbol table type)
157213
@enum.unique

spimdisasm/elf32/Elf32File.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from .. import common
1111

12-
from .Elf32Constants import Elf32HeaderIdentifier, Elf32ObjectFileType, Elf32HeaderFlag, Elf32SectionHeaderType, Elf32SymbolTableType, Elf32SymbolTableBinding, Elf32SymbolVisibility, Elf32SectionHeaderNumber
12+
from .Elf32Constants import Elf32HeaderIdentifier, Elf32ObjectFileType, Elf32HeaderFlag, Elf32SectionHeaderType, Elf32SectionHeaderFlag, Elf32SymbolTableType, Elf32SymbolTableBinding, Elf32SymbolVisibility, Elf32SectionHeaderNumber
1313
from .Elf32Dyns import Elf32Dyns
1414
from .Elf32GlobalOffsetTable import Elf32GlobalOffsetTable
1515
from .Elf32Header import Elf32Header
@@ -228,6 +228,10 @@ def _processSection_MIPS_MSYM(self, array_of_bytes: bytearray, entry: Elf32Secti
228228
# ?
229229
pass
230230

231+
def _processSection_MIPS_CONFLICT(self, array_of_bytes: bytearray, entry: Elf32SectionHeaderEntry, sectionEntryName: str) -> None:
232+
# ?
233+
pass
234+
231235
def _processSection_MIPS_GPTAB(self, array_of_bytes: bytearray, entry: Elf32SectionHeaderEntry, sectionEntryName: str) -> None:
232236
# ?
233237
pass
@@ -270,6 +274,7 @@ def _processSection_MIPS_ABIFLAGS(self, array_of_bytes: bytearray, entry: Elf32S
270274

271275
Elf32SectionHeaderType.MIPS_LIBLIST.value: _processSection_MIPS_LIBLIST,
272276
Elf32SectionHeaderType.MIPS_MSYM.value: _processSection_MIPS_MSYM,
277+
Elf32SectionHeaderType.MIPS_CONFLICT.value: _processSection_MIPS_CONFLICT,
273278
Elf32SectionHeaderType.MIPS_GPTAB.value: _processSection_MIPS_GPTAB,
274279
Elf32SectionHeaderType.MIPS_DEBUG.value: _processSection_MIPS_DEBUG,
275280
Elf32SectionHeaderType.MIPS_REGINFO.value: _processSection_MIPS_REGINFO,
@@ -381,6 +386,63 @@ def readelf_fileHeader(self) -> None:
381386
print(f" {'Section header string table index:':<34} {self.header.shstrndx}")
382387

383388

389+
def readelf_sectionHeaders(self) -> None:
390+
flagsKeys = {
391+
Elf32SectionHeaderFlag.WRITE: "W",
392+
Elf32SectionHeaderFlag.ALLOC: "A",
393+
Elf32SectionHeaderFlag.EXECINSTR: "X",
394+
Elf32SectionHeaderFlag.MERGE: "M",
395+
Elf32SectionHeaderFlag.STRINGS: "S",
396+
Elf32SectionHeaderFlag.INFO_LINK: "I",
397+
Elf32SectionHeaderFlag.LINK_ORDER: "L",
398+
Elf32SectionHeaderFlag.OS_NONCONFORMING: "O",
399+
Elf32SectionHeaderFlag.GROUP: "G",
400+
Elf32SectionHeaderFlag.TLS: "T",
401+
Elf32SectionHeaderFlag.COMPRESSED: "C",
402+
Elf32SectionHeaderFlag.EXCLUDE: "E",
403+
}
404+
405+
print(f"There are {len(self.sectionHeaders)} section headers, starting at offset 0x{self.sectionHeaders.shoff:X}:")
406+
print()
407+
408+
print(f"Section Headers:")
409+
410+
print(f" [{'Nr':>2}] {'Name':<17} {'Type':<15} {'Addr':<8} {'Off':<6} {'Size':<6} ES Flg Lk Inf Al")
411+
412+
i = 0
413+
for header in self.sectionHeaders:
414+
name = self.shstrtab[header.name]
415+
416+
headerType = Elf32SectionHeaderType.fromValue(header.type)
417+
headerTypeStr = f"<0x{header.type:X}>"
418+
if headerType is not None:
419+
headerTypeStr = headerType.name
420+
421+
flags, unknownFlags = Elf32SectionHeaderFlag.parseFlags(header.flags)
422+
flagsStr: str = ""
423+
for flag in flags:
424+
flagsStr += flagsKeys[flag]
425+
426+
if unknownFlags & 0x0FF00000:
427+
flagsStr += 'o'
428+
unknownFlags &= ~0x0FF00000
429+
if unknownFlags & 0xF0000000:
430+
flagsStr += 'p'
431+
unknownFlags &= ~0xF0000000
432+
433+
print(f" [{i:>2}] {name:<17} {headerTypeStr:<15} {header.addr:08X} {header.offset:06X} {header.size:06X} {header.entsize:02X} {flagsStr:>3} {header.link:> 2X} {header.info:> 3X} {header.addralign:>2X}")
434+
if unknownFlags:
435+
print(f"Warning unknown flags: 0x{unknownFlags:X}")
436+
437+
i += 1
438+
439+
print(f"Key to Flags:")
440+
print(f" W (write), A (alloc), X (execute), M (merge), S (strings), I (info),")
441+
print(f" L (link order), O (extra OS processing required), G (group), T (TLS),")
442+
print(f" C (compressed), x (unknown), o (OS specific), E (exclude),")
443+
print(f" D (mbind), p (processor specific)")
444+
445+
384446
def readelf_syms(self) -> None:
385447
if self.symtab is not None:
386448
print(f"Symbol table '.symtab' contains {len(self.symtab.symbols)} entries:")

spimdisasm/elf32/Elf32SectionHeaders.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,6 @@ def __getitem__(self, key: int) -> Elf32SectionHeaderEntry | None:
7070
def __iter__(self):
7171
for entry in self.sections:
7272
yield entry
73+
74+
def __len__(self) -> int:
75+
return len(self.sections)

spimdisasm/elf32/__init__.py

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

66
from __future__ import annotations
77

8-
from .Elf32Constants import Elf32HeaderIdentifier, Elf32ObjectFileType, Elf32HeaderFlag, Elf32SectionHeaderType, Elf32SymbolTableType, Elf32SymbolTableBinding, Elf32SymbolVisibility, Elf32SectionHeaderNumber, Elf32DynamicTable
8+
from .Elf32Constants import Elf32HeaderIdentifier, Elf32ObjectFileType
9+
from .Elf32Constants import Elf32HeaderFlag, Elf32SectionHeaderType, Elf32SectionHeaderFlag
10+
from .Elf32Constants import Elf32SymbolTableType, Elf32SymbolTableBinding, Elf32SymbolVisibility, Elf32SectionHeaderNumber
11+
from .Elf32Constants import Elf32DynamicTable
912
from .Elf32Dyns import Elf32Dyns, Elf32DynEntry
1013
from .Elf32GlobalOffsetTable import Elf32GlobalOffsetTable
1114
from .Elf32Header import Elf32Header

spimdisasm/elfObjDisasm/ElfObjDisasmInternals.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def addOptionsToParser(parser: argparse.ArgumentParser) -> argparse.ArgumentPars
4242

4343
readelfOptions.add_argument("-a", "--all", help="Equivalent to --file-header --syms --relocs --display-got", action="store_true")
4444
readelfOptions.add_argument("--file-header", help="Display the ELF file header", action="store_true")
45+
readelfOptions.add_argument("-S", "--section-headers", help="Display the sections' header", action="store_true")
4546
readelfOptions.add_argument("-s", "--syms", help="Display the symbol table", action="store_true")
4647
readelfOptions.add_argument("-r", "--relocs", help="Display the relocations (if present)", action="store_true")
4748
readelfOptions.add_argument("--display-got", help="Shows Global offset table information", action="store_true")
@@ -82,13 +83,17 @@ def applyGlobalConfigurations() -> None:
8283
def applyReadelfLikeFlags(elfFile: elf32.Elf32File, args: argparse.Namespace) -> None:
8384
if args.all:
8485
elfFile.readelf_fileHeader()
86+
elfFile.readelf_sectionHeaders()
8587
elfFile.readelf_syms()
8688
elfFile.readelf_relocs()
8789
elfFile.readelf_displayGot()
8890
else:
8991
if args.file_header:
9092
elfFile.readelf_fileHeader()
9193

94+
if args.section_headers:
95+
elfFile.readelf_sectionHeaders()
96+
9297
if args.syms:
9398
elfFile.readelf_syms()
9499

spimdisasm/frontendCommon/FrontendUtilities.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ def getSplittedSections(context: common.Context, splits: common.FileSplitFormat,
4242
outputPath = dataOutput
4343
elif row.section == common.FileSectionType.Bss:
4444
outputPath = dataOutput
45+
elif row.section == common.FileSectionType.Dummy:
46+
# Ignore dummy sections
47+
continue
4548
else:
4649
common.Utils.eprint("Error! Section not set!")
4750
exit(1)

0 commit comments

Comments
 (0)