Skip to content

Commit 97047c5

Browse files
authored
Add o segment type (#520)
* Add `o` segment type * ruff * Version bump * PR feedback
1 parent f6c3092 commit 97047c5

File tree

9 files changed

+129
-3
lines changed

9 files changed

+129
-3
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# splat Release Notes
22

3+
### 0.39.0
4+
5+
* New `o` segment allowing for a more granular way to include library objects.
36

47
### 0.38.1
58

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The brackets corresponds to the optional dependencies to install while installin
2121
If you use a `requirements.txt` file in your repository, then you can add this library with the following line:
2222

2323
```txt
24-
splat64[mips]>=0.38.1,<1.0.0
24+
splat64[mips]>=0.39.0,<1.0.0
2525
```
2626

2727
### Optional dependencies

docs/Configuration.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,17 @@ extensions_path: path/to/extensions/folder
384384

385385
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.
386386

387+
#### Default
388+
`lib`
389+
390+
391+
### o_path
392+
393+
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.
394+
395+
#### Default
396+
`build`
397+
387398

388399
### elf_section_list_path
389400
Path to file containing elf section list.

docs/Segments.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,26 @@ It looks for libraries in the [`lib_path`](https://github.com/ethteck/splat/wiki
290290
- { type: lib, name: a_lib, object: b_obj, section: .text }
291291
```
292292

293+
## `o`
294+
295+
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.
296+
297+
It looks for libraries in the [`o_path`](https://github.com/ethteck/splat/wiki/Configuration#o_path) global option.
298+
299+
```yaml
300+
# link to .text of myobject.o
301+
- [0x14040, o, myobject]
302+
```
303+
304+
```yaml
305+
# link to .rodata of myobject.o
306+
- [0x14240, o, myobject, .rodata]
307+
```
308+
309+
```yaml
310+
# link to .text of myobject.o (dict representation)
311+
- { start: 0x14040, type: o, name: myobject, section: .text }
312+
```
293313

294314
## `pad`
295315

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "splat64"
33
# Should be synced with src/splat/__init__.py
4-
version = "0.38.1"
4+
version = "0.39.0"
55
description = "A binary splitting tool to assist with decompilation and modding projects"
66
readme = "README.md"
77
license = {file = "LICENSE"}

src/splat/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
__package_name__ = __name__
22

33
# Should be synced with pyproject.toml
4-
__version__ = "0.38.1"
4+
__version__ = "0.39.0"
55
__author__ = "ethteck"
66

77
from . import util as util

src/splat/segtypes/common/o.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from typing import Optional
2+
3+
from pathlib import Path
4+
5+
from ...util import options
6+
from ..common.lib import CommonSegment
7+
from ..segment import parse_segment_vram
8+
9+
10+
class CommonSegO(CommonSegment):
11+
def __init__(
12+
self,
13+
rom_start: Optional[int],
14+
rom_end: Optional[int],
15+
type: str,
16+
name: str,
17+
vram_start: Optional[int],
18+
args: list,
19+
yaml,
20+
):
21+
super().__init__(
22+
rom_start,
23+
rom_end,
24+
type,
25+
name,
26+
vram_start,
27+
args=args,
28+
yaml=yaml,
29+
)
30+
31+
vram = parse_segment_vram(self.yaml)
32+
if vram is not None:
33+
self.vram_start = vram
34+
35+
if isinstance(yaml, dict):
36+
self.section = yaml.get("section", ".text")
37+
else:
38+
if len(args) > 0:
39+
self.section = args[0]
40+
else:
41+
self.section = ".text"
42+
43+
self.extract = False
44+
45+
def get_linker_section(self) -> str:
46+
return self.section
47+
48+
def out_path(self) -> Optional[Path]:
49+
out_path = options.opts.o_path / f"{self.name}"
50+
return out_path

src/splat/util/options.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ class SplatOpts:
9999

100100
# Determines the path to library files that are to be linked into the target binary
101101
lib_path: Path
102+
# Determines the path to object files that are to be linked into the target binary
103+
o_path: Path
102104

103105
# TODO document
104106
elf_section_list_path: Optional[Path]
@@ -502,6 +504,7 @@ def parse_include_asm_macro_style() -> Literal["default", "maspsx_hack"]:
502504
),
503505
extensions_path=p.parse_optional_path(base_path, "extensions_path"),
504506
lib_path=p.parse_path(base_path, "lib_path", "lib"),
507+
o_path=p.parse_path(base_path, "o_path", "build"),
505508
elf_section_list_path=p.parse_optional_path(base_path, "elf_section_list_path"),
506509
subalign=p.parse_optional_opt_with_default("subalign", int, 16),
507510
emit_subalign=p.parse_opt("emit_subalign", bool, True),

test.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from src.splat.segtypes.common.code import CommonSegCode
1717
from src.splat.segtypes.common.c import CommonSegC
1818
from src.splat.segtypes.common.bss import CommonSegBss
19+
from src.splat.segtypes.common.o import CommonSegO
1920
from src.splat.segtypes.segment import Segment
2021

2122

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

370371

372+
class Object(unittest.TestCase):
373+
def test_o_text(self):
374+
# Segment __init__ requires opts to be initialized
375+
test_init()
376+
377+
o = CommonSegO(
378+
rom_start=0x100,
379+
rom_end=0x200,
380+
vram_start=0x0,
381+
type="o",
382+
name="myobject",
383+
args=[],
384+
yaml=None,
385+
)
386+
expected = Path("test/basic_app/build/myobject")
387+
self.assertEqual(expected, o.out_path())
388+
self.assertEqual(".text", o.get_linker_section())
389+
390+
def test_o_rodata(self):
391+
# Segment __init__ requires opts to be initialized
392+
test_init()
393+
394+
section = ".rodata"
395+
o = CommonSegO(
396+
rom_start=0x100,
397+
rom_end=0x200,
398+
vram_start=0x0,
399+
type="o",
400+
name="myobject",
401+
args=[section],
402+
yaml=None,
403+
)
404+
out_path = Path("test/basic_app/build/myobject")
405+
406+
self.assertEqual(out_path, o.out_path())
407+
self.assertEqual(section, o.get_linker_section())
408+
409+
371410
class SymbolsInitialize(unittest.TestCase):
372411
def test_attrs(self):
373412
symbols.reset_symbols()

0 commit comments

Comments
 (0)