Skip to content

Commit

Permalink
Implement section_order
Browse files Browse the repository at this point in the history
Fixes #44
  • Loading branch information
AngheloAlf committed Feb 28, 2024
1 parent e01a868 commit dac24e8
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 2 deletions.
40 changes: 40 additions & 0 deletions docs/file_format/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,43 @@ This name is not used as-is, instead it is controlled by the global
### Valid values

Non empty string.

## `section_order`

Allows to specify that one or more sections of this file should be put within
other specific sections.

Each key represents a section to be placed elsewhere and its key represent the
section where it should be put on.

### Example

```yaml
settings:
base_path: build
segments:
- name: code
files:
- { path: src/code/main.o }
- { path: src/code/message.o, section_order: { .data: .rodata } }
- { path: src/code/collisions.o }
```

The above example would produce an ordering like the following:

```bash
build/src/code/main.o(.data*);
build/src/code/collisions.o(.data*); # Notice no entry for message(.data)
# snip
build/src/code/main.o(.rodata*);
build/src/code/message.o(.data*);
build/src/code/message.o(.rodata*);
build/src/code/collisions.o(.rodata*);
```

### Valid values

A dictionary (map) of non empty string as keys and values.
26 changes: 25 additions & 1 deletion slinky/src/file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
/* SPDX-License-Identifier: MIT */

use serde::Deserialize;
use std::path::{Path, PathBuf};
use std::{
collections::HashMap,
path::{Path, PathBuf},
};

use crate::{absent_nullable::AbsentNullable, file_kind::FileKind, Settings, SlinkyError};

Expand All @@ -19,6 +22,8 @@ pub struct FileInfo {
pub section: String,

pub linker_offset_name: String,

pub section_order: HashMap<String, String>,
}

#[derive(Deserialize, PartialEq, Debug)]
Expand All @@ -40,6 +45,9 @@ pub(crate) struct FileInfoSerial {

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

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

impl FileInfoSerial {
Expand Down Expand Up @@ -136,13 +144,29 @@ impl FileInfoSerial {
FileKind::LinkerOffset => self.linker_offset_name.get("linker_offset_name")?,
};

let section_order = match kind {
FileKind::Pad | FileKind::LinkerOffset => {
if self.section_order.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "section_order".into(),
field2: "non `kind: object` or `kind: archive`".into(),
});
}
HashMap::default()
}
FileKind::Object | FileKind::Archive => self
.section_order
.get_non_null("section_order", HashMap::default)?,
};

Ok(FileInfo {
path,
kind,
subfile,
pad_amount,
section,
linker_offset_name,
section_order,
})
}
}
17 changes: 17 additions & 0 deletions slinky/src/linker_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,23 @@ impl LinkerWriter<'_> {

fn emit_section(&mut self, segment: &Segment, section: &str) {
for file in &segment.files {
if !file.section_order.is_empty() {
// Keys specify the section and value specify where it will be put
// For example: `section_order: { .data: .rodata }`, meaning the `.data` of the file should be put within its `.rodata`

// This section should be placed somewhere else
if file.section_order.contains_key(section) {
continue;
}

// Check if any other section should be placed be placed here
for (k, v) in &file.section_order {
if v == section {
self.emit_file(file, segment, k);
}
}
}

self.emit_file(file, segment, section);
}
}
Expand Down
6 changes: 6 additions & 0 deletions tests/input_files/makerom_zelda_like.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ segments:
files:
- { path: boot/boot_main.o }

- name: code
files:
- { path: src/code/main.o }
- { path: src/code/z_game_over.o, section_order: { .data: .rodata } }
- { path: src/code/z_message_PAL.o, section_order: { .data: .rodata } }

- name: gameplay_keep
fixed_vram: 0x04000000
segment_start_align: 0x1000
Expand Down
85 changes: 85 additions & 0 deletions tests/linker_scripts/makerom_zelda_like.ld
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,91 @@ SECTIONS
_bootSegmentRomEnd = __romPos;
_bootSegmentRomSize = ABSOLUTE(_bootSegmentRomEnd - _bootSegmentRomStart);

_codeSegmentRomStart = __romPos;
_codeSegmentStart = ADDR(.code);
_code_allocSegmentStart = .;
.code : AT(_codeSegmentRomStart)
{
FILL(0x00000000);
_codeSegmentTextStart = .;
build/src/code/main.o(.text*);
build/src/code/z_game_over.o(.text*);
build/src/code/z_message_PAL.o(.text*);
. = ALIGN(., 0x10);
_codeSegmentTextEnd = .;
_codeSegmentTextSize = ABSOLUTE(_codeSegmentTextEnd - _codeSegmentTextStart);

_codeSegmentDataStart = .;
build/src/code/main.o(.data*);
. = ALIGN(., 0x10);
_codeSegmentDataEnd = .;
_codeSegmentDataSize = ABSOLUTE(_codeSegmentDataEnd - _codeSegmentDataStart);

_codeSegmentRoDataStart = .;
build/src/code/main.o(.rodata*);
build/src/code/z_game_over.o(.data*);
build/src/code/z_game_over.o(.rodata*);
build/src/code/z_message_PAL.o(.data*);
build/src/code/z_message_PAL.o(.rodata*);
. = ALIGN(., 0x10);
_codeSegmentRoDataEnd = .;
_codeSegmentRoDataSize = ABSOLUTE(_codeSegmentRoDataEnd - _codeSegmentRoDataStart);

_codeSegmentSdataStart = .;
build/src/code/main.o(.sdata*);
build/src/code/z_game_over.o(.sdata*);
build/src/code/z_message_PAL.o(.sdata*);
. = ALIGN(., 0x10);
_codeSegmentSdataEnd = .;
_codeSegmentSdataSize = ABSOLUTE(_codeSegmentSdataEnd - _codeSegmentSdataStart);
}
_code_allocSegmentEnd = .;
_code_allocSegmentSize = ABSOLUTE(_code_allocSegmentEnd - _code_allocSegmentStart);

_code_noloadSegmentStart = .;
.code.noload (NOLOAD) :
{
FILL(0x00000000);
_codeSegmentSbssStart = .;
build/src/code/main.o(.sbss*);
build/src/code/z_game_over.o(.sbss*);
build/src/code/z_message_PAL.o(.sbss*);
. = ALIGN(., 0x10);
_codeSegmentSbssEnd = .;
_codeSegmentSbssSize = ABSOLUTE(_codeSegmentSbssEnd - _codeSegmentSbssStart);

_codeSegmentScommonStart = .;
build/src/code/main.o(.scommon*);
build/src/code/z_game_over.o(.scommon*);
build/src/code/z_message_PAL.o(.scommon*);
. = ALIGN(., 0x10);
_codeSegmentScommonEnd = .;
_codeSegmentScommonSize = ABSOLUTE(_codeSegmentScommonEnd - _codeSegmentScommonStart);

_codeSegmentBssStart = .;
build/src/code/main.o(.bss*);
build/src/code/z_game_over.o(.bss*);
build/src/code/z_message_PAL.o(.bss*);
. = ALIGN(., 0x10);
_codeSegmentBssEnd = .;
_codeSegmentBssSize = ABSOLUTE(_codeSegmentBssEnd - _codeSegmentBssStart);

_codeSegmentCOMMONStart = .;
build/src/code/main.o(COMMON*);
build/src/code/z_game_over.o(COMMON*);
build/src/code/z_message_PAL.o(COMMON*);
. = ALIGN(., 0x10);
_codeSegmentCOMMONEnd = .;
_codeSegmentCOMMONSize = ABSOLUTE(_codeSegmentCOMMONEnd - _codeSegmentCOMMONStart);
}
_code_noloadSegmentEnd = .;
_code_noloadSegmentSize = ABSOLUTE(_code_noloadSegmentEnd - _code_noloadSegmentStart);
_codeSegmentEnd = .;
_codeSegmentSize = ABSOLUTE(_codeSegmentEnd - _codeSegmentStart);
__romPos += SIZEOF(.code);
_codeSegmentRomEnd = __romPos;
_codeSegmentRomSize = ABSOLUTE(_codeSegmentRomEnd - _codeSegmentRomStart);

__romPos = ALIGN(__romPos, 0x1000);
. = ALIGN(., 0x1000);
_gameplay_keepSegmentRomStart = __romPos;
Expand Down
2 changes: 1 addition & 1 deletion tests/regen_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ for filepath in tests/input_files/*.yaml; do
stem="${filename%.*}"
output=tests/linker_scripts/$stem.ld
echo Generating $output
cargo run -- $filepath -o $output
cargo run --release -- $filepath -o $output
#for ((i=0; i<=3; i++)); do
# ./MyProgram.exe "$filename" "Logs/$(basename "$filename" .txt)_Log$i.txt"
#done
Expand Down

0 comments on commit dac24e8

Please sign in to comment.