Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add settings to toggle %gp_rel usage on generated assembly #392

Merged
merged 4 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
# splat Release Notes

### 0.25.2

* Two new yaml options: `use_gp_rel_macro_nonmatching` and `use_gp_rel_macro`
* Allows to toggle the use of `%gp_rel`s.
* Not using `%gp_rel`s may be desirable for projects that use old assemblers that do not support said relocation parameter.
* The assembler is free to choose the kind of relocation to use if no explicit relocation parameter is used for a given instruction, it may even expand the instruction into multiple instructions. To avoid this, it is the user's responsability to provide the symbol's information (like the symbol's size) to the assembler so it can pick the correct relocation.

### 0.25.1

* Added two new segment types: `gcc_except_table` and `eh_frame`.
* Used by GCC to handle C++ exceptions.
* New yaml option: `asm_jtbl_label_macro`
* New yaml option: `asm_ehtable_label_macro`
* Allows to specify the macro used by ehlabels, the ones generated by `gcc_except_table` references.

### 0.25.0
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The brackets corresponds to the optional dependencies to install while installin
If you use a `requirements.txt` file in your repository, then you can add this library with the following line:

```txt
splat64[mips]>=0.25.1,<1.0.0
splat64[mips]>=0.25.2,<1.0.0
```

### Optional dependencies
Expand Down
20 changes: 20 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,26 @@ Allow specifying that the global memory range may be larger than what was automa

Useful for projects where splat is used in multiple individual files, meaning the expected global segment may not be properly detected because each instance of splat can't see the info from other files, like in PSX and PSP projects.

### use_gp_rel_macro_nonmatching

If True then use the `%gp_rel` explicit relocation parameter on instructions that use the $gp register, otherwise strip the `%gp_rel` parameter entirely
and convert those instructions into macro instructions that may not assemble to the original bytes.

In the latter case, it is the user's responsability to provide the symbol's information to the assembler so it can assemble the instruction with the
proper relocation, for example by declaring the required symbol on the corresponding `.c` or `.cpp` file.

Turning off this setting may be useful for projects with old assemblers that do not support `%gp_rel`, like PS2 and PSP projects.

This setting is applied exclusively to `c` segments (functions under the nonmatchings folder).

Defaults to `True`

### use_gp_rel_macro

Does the same as `use_gp_rel_macro_nonmatching`, except it is only applied to `asm` and `hasm` segments.

Defaults to `True`

## N64-specific options

### header_encoding
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[project]
name = "splat64"
# Should be synced with src/splat/__init__.py
version = "0.25.1"
version = "0.25.2"
description = "A binary splitting tool to assist with decompilation and modding projects"
readme = "README.md"
license = {file = "LICENSE"}
Expand All @@ -20,7 +20,7 @@ dependencies = [

[project.optional-dependencies]
mips = [
"spimdisasm>=1.27.0,<2.0.0", # This value should be keep in sync with the version listed on disassembler/spimdisasm_disassembler.py
"spimdisasm>=1.28.0,<2.0.0", # This value should be keep in sync with the version listed on disassembler/spimdisasm_disassembler.py
"rabbitizer>=1.10.0,<2.0.0",
"pygfxd",
"n64img>=0.1.4",
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ tqdm
intervaltree
colorama
# This value should be keep in sync with the version listed on disassembler/spimdisasm_disassembler.py and pyproject.toml
spimdisasm>=1.26.0
spimdisasm>=1.28.0
rabbitizer>=1.10.0
pygfxd
n64img>=0.1.4
Expand Down
2 changes: 1 addition & 1 deletion src/splat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
__package_name__ = __name__

# Should be synced with pyproject.toml
__version__ = "0.25.0"
__version__ = "0.25.2"
__author__ = "ethteck"

from . import util as util
Expand Down
2 changes: 1 addition & 1 deletion src/splat/disassembler/spimdisasm_disassembler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

class SpimdisasmDisassembler(disassembler.Disassembler):
# This value should be kept in sync with the version listed on requirements.txt and pyproject.toml
SPIMDISASM_MIN = (1, 27, 0)
SPIMDISASM_MIN = (1, 28, 0)

def configure(self):
# Configure spimdisasm
Expand Down
2 changes: 2 additions & 0 deletions src/splat/segtypes/common/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ def __init__(self, *args, **kwargs):

self.file_extension = "c"

self.use_gp_rel_macro = options.opts.use_gp_rel_macro_nonmatching

@staticmethod
def strip_c_comments(text):
def replacer(match):
Expand Down
2 changes: 2 additions & 0 deletions src/splat/segtypes/common/codesubsegment.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def __init__(self, *args, **kwargs):
)

self.is_hasm = False
self.use_gp_rel_macro = options.opts.use_gp_rel_macro

@property
def needs_symbols(self) -> bool:
Expand All @@ -59,6 +60,7 @@ def configure_disassembler_section(
section.isHandwritten = self.is_hasm
section.instrCat = self.instr_category
section.detectRedundantFunctionEnd = self.detect_redundant_function_end
section.gpRelHack = not self.use_gp_rel_macro

def scan_code(self, rom_bytes, is_hasm=False):
self.is_hasm = is_hasm
Expand Down
14 changes: 13 additions & 1 deletion src/splat/util/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class SplatOpts:
asm_data_macro: str
# Determines the macro used at the end of a function, such as endlabel or .end
asm_end_label: str
# Determines the macro used to declare data symbols in asm files
# Determines the macro used to declare ehtable labels in asm files
asm_ehtable_label_macro: str
# Toggles the .size directive emitted by the disassembler
asm_emit_size_directive: Optional[bool]
Expand Down Expand Up @@ -226,6 +226,14 @@ class SplatOpts:
# Useful for projects where splat is used in multiple individual files, meaning the expected global segment may not be properly detected because each instance of splat can't see the info from other files.
global_vram_start: Optional[int]
global_vram_end: Optional[int]
# For `c` segments (functions under the nonmatchings folder).
# If True then use the `%gp_rel` explicit relocation parameter on instructions that use the $gp register,
# otherwise strip the `%gp_rel` parameter entirely and convert those instructions into macro instructions that may not assemble to the original
# bytes. In the latter case, it is the user's responsability to provide the symbol's information to the assembler so it can assemble the
# instruction with the proper relocation.
use_gp_rel_macro_nonmatching: bool
# Does the same as `use_gp_rel_macro_nonmatching`, except it is only applied to `asm` and `hasm` segments.
use_gp_rel_macro: bool

################################################################################
# N64-specific options
Expand Down Expand Up @@ -550,6 +558,10 @@ def parse_endianness() -> Literal["big", "little"]:
),
global_vram_start=p.parse_optional_opt("global_vram_start", int),
global_vram_end=p.parse_optional_opt("global_vram_end", int),
use_gp_rel_macro_nonmatching=p.parse_opt(
"use_gp_rel_macro_nonmatching", bool, True
),
use_gp_rel_macro=p.parse_opt("use_gp_rel_macro", bool, True),
)
p.check_no_unread_opts()
return ret
Expand Down