Skip to content

Commit

Permalink
Implement linker_offset
Browse files Browse the repository at this point in the history
Fixes #35
  • Loading branch information
AngheloAlf committed Feb 27, 2024
1 parent 78ace52 commit ad8bf9b
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 25 deletions.
31 changes: 22 additions & 9 deletions docs/file_format/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ Specifies the type of file entry.
### Example

The following example forces the position of the linker script to advance 0x10
bytes after the the `boot_main.o` file, but only for the `.text` pad_section.
bytes after the the `boot_main.o` file, but only for the `.text` section.

```yaml
segments:
- name: boot
files:
- { path: src/boot/boot_main.o }
- { kind: pad, pad_amount: 0x10, pad_section: .text }
- { kind: pad, pad_amount: 0x10, section: .text }
- { path: src/boot/dmadata.o }
```

Expand All @@ -49,9 +49,11 @@ segments:
- `object`: The path points to a relocatable object file. The [`path`](#path) is
required.
- `pad`: Do not link any file but increment the position of the
[`pad_section`](#pad_section) in the linker script by
[`pad_amount`](#pad_amount) bytes. Both [`pad_section`](#pad_section) and
[`pad_amount`](#pad_amount) are required.
[`section`](#section) in the linker script by [`pad_amount`](#pad_amount)
bytes. Both [`section`](#section) and [`pad_amount`](#pad_amount) are required.
- `linker_offset`: Emit a symbol between the files at a given
[`section`](#section). Both [`section`](#section) and
[`linker_offset_name`](#linker_offset_name) are required.

### Default value

Expand All @@ -71,20 +73,31 @@ The amount of bytes to increment the position in the linker script used on `pad`
segments:
- name: boot
files:
- { kind: pad, pad_amount: 0x10, pad_section: .text }
- { kind: pad, pad_amount: 0x10, section: .text }
```

### Valid values

Positive integers.

## `pad_section`
## `section`

This field have different meanings depending on the file [`kind`](#kind):

- `object`: This field is invalid.
- `pad`: The position of the linker script will advance only for this
pad_section.
- `pad`: The position of the linker script will advance only for this section.
- `linker_offset`: The section where the linker offset symbol will be emitted.

### Valid values

Non empty string.

## `linker_offset_name`

The name to be used for the generated `linker offset` [`kind`](#kind).

This name is not used as-is, instead it is controlled by the global
[`linker_symbols_style`](settings.md#linker_symbols_style) setting

### Valid values

Expand Down
2 changes: 2 additions & 0 deletions docs/file_format/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ settings:
- `.text`: `boot_TEXT_START`, `boot_TEXT_END` and `boot_TEXT_SIZE`.
- `.data`: `boot_DATA_START`, `boot_DATA_END` and `boot_DATA_SIZE`.
- `.bss`: `boot_BSS_START`, `boot_BSS_END` and `boot_BSS_SIZE`.
- File [`linker_offset_name`](file.md#linker_offset_name): `{name}_OFFSET`

- `makerom`: Produces _camelCase symbols. Given a segment named `boot`:
- Segment rom: `_bootSegmentRomStart`, `_bootSegmentRomEnd` and `_bootSegmentRomSize`.
Expand All @@ -69,6 +70,7 @@ settings:
- `.text`: `_bootSegmentTextStart`, `_bootSegmentTextEnd` and `_bootSegmentTextSize`.
- `.data`: `_bootSegmentDataStart`, `_bootSegmentDataEnd` and `_bootSegmentDataSize`.
- `.bss`: `_bootSegmentBssStart`, `_bootSegmentBssEnd` and `_bootSegmentBssSize`.
- File [`linker_offset_name`](file.md#linker_offset_name): `_{name}Offset`

### Default value

Expand Down
39 changes: 29 additions & 10 deletions slinky/src/file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ pub struct FileInfo {
pub kind: FileKind,

pub pad_amount: u32,
pub pad_section: String,
pub section: String,

pub linker_offset_name: String,
}

#[derive(Deserialize, PartialEq, Debug)]
Expand All @@ -28,7 +30,10 @@ pub(crate) struct FileInfoSerial {
#[serde(default)]
pub pad_amount: AbsentNullable<u32>,
#[serde(default)]
pub pad_section: AbsentNullable<String>,
pub section: AbsentNullable<String>,

#[serde(default)]
pub linker_offset_name: AbsentNullable<String>,
}

impl FileInfoSerial {
Expand All @@ -47,11 +52,11 @@ impl FileInfoSerial {

(p, k)
}
FileKind::Pad => {
FileKind::Pad | FileKind::LinkerOffset => {
// pad doesn't allow for paths
if self.path.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "kind: pad".into(),
field1: "kind: pad or kind: linker_offset".into(),
field2: "path".into(),
});
}
Expand All @@ -74,7 +79,7 @@ impl FileInfoSerial {
};

let pad_amount = match kind {
FileKind::Object => {
FileKind::Object | FileKind::LinkerOffset => {
if self.pad_amount.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "pad_amount".into(),
Expand All @@ -86,24 +91,38 @@ impl FileInfoSerial {
FileKind::Pad => self.pad_amount.get("pad_amount")?,
};

let pad_section = match kind {
let section = match kind {
FileKind::Object => {
if self.pad_section.has_value() {
if self.section.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "pad_section".into(),
field1: "section".into(),
field2: "non `kind: pad`".into(),
});
}
"".into()
}
FileKind::Pad => self.pad_section.get("pad_section")?,
FileKind::Pad | FileKind::LinkerOffset => self.section.get("section")?,
};

let linker_offset_name = match kind {
FileKind::Object | FileKind::Pad => {
if self.linker_offset_name.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "linker_offset_name".into(),
field2: "non `kind: linker_offset`".into(),
});
}
"".into()
}
FileKind::LinkerOffset => self.linker_offset_name.get("linker_offset_name")?,
};

Ok(FileInfo {
path,
kind,
pad_amount,
pad_section,
section,
linker_offset_name,
})
}
}
1 change: 1 addition & 0 deletions slinky/src/file_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub enum FileKind {
Object,
// Archive,
Pad,
LinkerOffset,
}

impl FileKind {
Expand Down
7 changes: 7 additions & 0 deletions slinky/src/linker_symbols_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,11 @@ impl LinkerSymbolsStyle {
LinkerSymbolsStyle::Makerom => format!("_{}Segment{}Size", seg_name, sec),
}
}

pub fn linker_offset(&self, name: &str) -> String {
match self {
LinkerSymbolsStyle::Splat => format!("{}_OFFSET", name),
LinkerSymbolsStyle::Makerom => format!("_{}Offset", name),
}
}
}
9 changes: 8 additions & 1 deletion slinky/src/linker_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ impl LinkerWriter<'_> {
}

fn write_files_for_section(&mut self, segment: &Segment, section: &str) {
let style = &self.settings.linker_symbols_style;

for file in &segment.files {
let mut path = self.settings.base_path.clone();

Expand All @@ -297,10 +299,15 @@ impl LinkerWriter<'_> {
}
//FileKind::Archive => todo!(),
FileKind::Pad => {
if file.pad_section == section {
if file.section == section {
self.writeln(&format!(". += 0x{:X};", file.pad_amount));
}
}
FileKind::LinkerOffset => {
if file.section == section {
self.write_symbol(&style.linker_offset(&file.linker_offset_name), ".");
}
}
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions tests/input_files/linker_offset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
settings:
base_path: build

segments:
- name: main
files:
- { kind: linker_offset, linker_offset_name: main_data_start, section: .data }
- { path: src/main/boot_main.o }
- { path: src/main/dmadata.o }
- { path: asm/main/util.o }
- { kind: linker_offset, linker_offset_name: libultra_start, section: .text }
- { path: src/libultra/libc/bzero.o }
6 changes: 3 additions & 3 deletions tests/input_files/pad_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ segments:
- name: boot
files:
- { path: src/boot/boot_main.o }
- { kind: pad, pad_amount: 0x40, pad_section: .text }
- { kind: pad, pad_amount: 0x40, section: .text }
- { path: src/boot/dmadata.o }
- { kind: pad, pad_amount: 0x20, pad_section: .rodata }
- { kind: pad, pad_amount: 0x20, section: .rodata }
- { path: asm/util.o }
- { kind: pad, pad_amount: 0x60, pad_section: .bss }
- { kind: pad, pad_amount: 0x60, section: .bss }
- { path: src/boot/unused_file.o }
107 changes: 107 additions & 0 deletions tests/linker_scripts/linker_offset.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
SECTIONS
{
__romPos = 0x0;

main_ROM_START = __romPos;
main_VRAM = ADDR(.main);
main_alloc_VRAM = .;
.main : AT(main_ROM_START) SUBALIGN(16)
{
FILL(0x00000000);
main_TEXT_START = .;
build/src/main/boot_main.o(.text*);
build/src/main/dmadata.o(.text*);
build/asm/main/util.o(.text*);
libultra_start_OFFSET = .;
build/src/libultra/libc/bzero.o(.text*);
main_TEXT_END = .;
main_TEXT_SIZE = ABSOLUTE(main_TEXT_END - main_TEXT_START);

main_DATA_START = .;
main_data_start_OFFSET = .;
build/src/main/boot_main.o(.data*);
build/src/main/dmadata.o(.data*);
build/asm/main/util.o(.data*);
build/src/libultra/libc/bzero.o(.data*);
main_DATA_END = .;
main_DATA_SIZE = ABSOLUTE(main_DATA_END - main_DATA_START);

main_RODATA_START = .;
build/src/main/boot_main.o(.rodata*);
build/src/main/dmadata.o(.rodata*);
build/asm/main/util.o(.rodata*);
build/src/libultra/libc/bzero.o(.rodata*);
main_RODATA_END = .;
main_RODATA_SIZE = ABSOLUTE(main_RODATA_END - main_RODATA_START);

main_SDATA_START = .;
build/src/main/boot_main.o(.sdata*);
build/src/main/dmadata.o(.sdata*);
build/asm/main/util.o(.sdata*);
build/src/libultra/libc/bzero.o(.sdata*);
main_SDATA_END = .;
main_SDATA_SIZE = ABSOLUTE(main_SDATA_END - main_SDATA_START);
}
main_alloc_VRAM_END = .;
main_alloc_VRAM_SIZE = ABSOLUTE(main_alloc_VRAM_END - main_alloc_VRAM);

main_noload_VRAM = .;
.main.noload (NOLOAD) : SUBALIGN(16)
{
FILL(0x00000000);
main_SBSS_START = .;
build/src/main/boot_main.o(.sbss*);
build/src/main/dmadata.o(.sbss*);
build/asm/main/util.o(.sbss*);
build/src/libultra/libc/bzero.o(.sbss*);
main_SBSS_END = .;
main_SBSS_SIZE = ABSOLUTE(main_SBSS_END - main_SBSS_START);

main_SCOMMON_START = .;
build/src/main/boot_main.o(.scommon*);
build/src/main/dmadata.o(.scommon*);
build/asm/main/util.o(.scommon*);
build/src/libultra/libc/bzero.o(.scommon*);
main_SCOMMON_END = .;
main_SCOMMON_SIZE = ABSOLUTE(main_SCOMMON_END - main_SCOMMON_START);

main_BSS_START = .;
build/src/main/boot_main.o(.bss*);
build/src/main/dmadata.o(.bss*);
build/asm/main/util.o(.bss*);
build/src/libultra/libc/bzero.o(.bss*);
main_BSS_END = .;
main_BSS_SIZE = ABSOLUTE(main_BSS_END - main_BSS_START);

mainCOMMON_START = .;
build/src/main/boot_main.o(COMMON*);
build/src/main/dmadata.o(COMMON*);
build/asm/main/util.o(COMMON*);
build/src/libultra/libc/bzero.o(COMMON*);
mainCOMMON_END = .;
mainCOMMON_SIZE = ABSOLUTE(mainCOMMON_END - mainCOMMON_START);
}
main_noload_VRAM_END = .;
main_noload_VRAM_SIZE = ABSOLUTE(main_noload_VRAM_END - main_noload_VRAM);
main_VRAM_END = .;
main_VRAM_SIZE = ABSOLUTE(main_VRAM_END - main_VRAM);
__romPos += SIZEOF(.main);
main_ROM_END = __romPos;
main_ROM_SIZE = ABSOLUTE(main_ROM_END - main_ROM_START);

.shstrtab 0 :
{
*(.shstrtab);
}

/DISCARD/ :
{
*(.reginfo);
*(.MIPS.abiflags);
*(.MIPS.options);
*(.note.gnu.build-id);
*(.interp);
*(.eh_frame);
*(*);
}
}
7 changes: 7 additions & 0 deletions tests/panics/kind_offset_no_name.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
settings:
base_path: build

segments:
- name: main
files:
- { kind: linker_offset, section: .data }
2 changes: 1 addition & 1 deletion tests/panics/kind_pad_no_amount.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
segments:
- name: main
files:
- { kind: pad, pad_section: .text }
- { kind: pad, section: .text }
2 changes: 1 addition & 1 deletion tests/panics/section_non_kind_pad.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
segments:
- name: main
files:
- { path: src/boot/boot_main.o, pad_section: .text }
- { path: src/boot/boot_main.o, section: .text }

0 comments on commit ad8bf9b

Please sign in to comment.