Skip to content
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# splat Release Notes

### 0.39.0

* New `o` segment allowing for a more granular way to include library objects.

### 0.38.1

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.38.1,<1.0.0
splat64[mips]>=0.39.0,<1.0.0
```

### Optional dependencies
Expand Down
11 changes: 11 additions & 0 deletions docs/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,17 @@ extensions_path: path/to/extensions/folder

Determines the path to library files that are to be linked into the target binary when the [`lib`](https://github.com/ethteck/splat/wiki/Segments#lib) segment type is used.

#### Default
`lib`


### o_path

Determines the path to object files that are to be linked into the target binary when the [`o`](https://github.com/ethteck/splat/wiki/Segments#o) segment type is used.

#### Default
`build`


### elf_section_list_path
Path to file containing elf section list.
Expand Down
20 changes: 20 additions & 0 deletions docs/Segments.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,26 @@ It looks for libraries in the [`lib_path`](https://github.com/ethteck/splat/wiki
- { type: lib, name: a_lib, object: b_obj, section: .text }
```

## `o`

Similar to the `lib` segment but this subsegment is used to reference an object file (for example extracted from a shared library file). Does not extract anything from the input binary.

It looks for libraries in the [`o_path`](https://github.com/ethteck/splat/wiki/Configuration#o_path) global option.

```yaml
# link to .text of myobject.o
- [0x14040, o, myobject]
```

```yaml
# link to .rodata of myobject.o
- [0x14240, o, myobject, .rodata]
```

```yaml
# link to .text of myobject.o (dict representation)
- { start: 0x14040, type: o, name: myobject, section: .text }
```

## `pad`

Expand Down
2 changes: 1 addition & 1 deletion 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.38.1"
version = "0.39.0"
description = "A binary splitting tool to assist with decompilation and modding projects"
readme = "README.md"
license = {file = "LICENSE"}
Expand Down
2 changes: 1 addition & 1 deletion src/splat/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
__package_name__ = __name__

# Should be synced with pyproject.toml
__version__ = "0.38.1"
__version__ = "0.39.0"
__author__ = "ethteck"

from . import util as util
Expand Down
50 changes: 50 additions & 0 deletions src/splat/segtypes/common/o.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from typing import Optional

from pathlib import Path

from ...util import options
from ..common.lib import CommonSegment
from ..segment import parse_segment_vram


class CommonSegO(CommonSegment):
def __init__(
self,
rom_start: Optional[int],
rom_end: Optional[int],
type: str,
name: str,
vram_start: Optional[int],
args: list,
yaml,
):
super().__init__(
rom_start,
rom_end,
type,
name,
vram_start,
args=args,
yaml=yaml,
)

vram = parse_segment_vram(self.yaml)
if vram is not None:
self.vram_start = vram

if isinstance(yaml, dict):
self.section = yaml.get("section", ".text")
else:
if len(args) > 0:
self.section = args[0]
else:
self.section = ".text"

self.extract = False

def get_linker_section(self) -> str:
return self.section

def out_path(self) -> Optional[Path]:
out_path = options.opts.o_path / f"{self.name}"
return out_path
3 changes: 3 additions & 0 deletions src/splat/util/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class SplatOpts:

# Determines the path to library files that are to be linked into the target binary
lib_path: Path
# Determines the path to object files that are to be linked into the target binary
o_path: Path

# TODO document
elf_section_list_path: Optional[Path]
Expand Down Expand Up @@ -502,6 +504,7 @@ def parse_include_asm_macro_style() -> Literal["default", "maspsx_hack"]:
),
extensions_path=p.parse_optional_path(base_path, "extensions_path"),
lib_path=p.parse_path(base_path, "lib_path", "lib"),
o_path=p.parse_path(base_path, "o_path", "build"),
elf_section_list_path=p.parse_optional_path(base_path, "elf_section_list_path"),
subalign=p.parse_optional_opt_with_default("subalign", int, 16),
emit_subalign=p.parse_opt("emit_subalign", bool, True),
Expand Down
39 changes: 39 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from src.splat.segtypes.common.code import CommonSegCode
from src.splat.segtypes.common.c import CommonSegC
from src.splat.segtypes.common.bss import CommonSegBss
from src.splat.segtypes.common.o import CommonSegO
from src.splat.segtypes.segment import Segment


Expand Down Expand Up @@ -368,6 +369,44 @@ def test_disassemble_data(self):
assert bss.spim_section.get_section().bssVramEnd == 0x300


class Object(unittest.TestCase):
def test_o_text(self):
# Segment __init__ requires opts to be initialized
test_init()

o = CommonSegO(
rom_start=0x100,
rom_end=0x200,
vram_start=0x0,
type="o",
name="myobject",
args=[],
yaml=None,
)
expected = Path("test/basic_app/build/myobject")
self.assertEqual(expected, o.out_path())
self.assertEqual(".text", o.get_linker_section())

def test_o_rodata(self):
# Segment __init__ requires opts to be initialized
test_init()

section = ".rodata"
o = CommonSegO(
rom_start=0x100,
rom_end=0x200,
vram_start=0x0,
type="o",
name="myobject",
args=[section],
yaml=None,
)
out_path = Path("test/basic_app/build/myobject")

self.assertEqual(out_path, o.out_path())
self.assertEqual(section, o.get_linker_section())


class SymbolsInitialize(unittest.TestCase):
def test_attrs(self):
symbols.reset_symbols()
Expand Down
Loading