From b6e4581937dff28f4534e393907124182fb791d0 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sat, 9 May 2020 15:41:49 -0400 Subject: [PATCH 1/7] Add mipsel-sony-psp target --- src/librustc_target/spec/mipsel_sony_psp.rs | 59 ++++ .../spec/mipsel_sony_psp_linker_script.ld | 289 ++++++++++++++++++ src/librustc_target/spec/mod.rs | 2 + 3 files changed, 350 insertions(+) create mode 100644 src/librustc_target/spec/mipsel_sony_psp.rs create mode 100644 src/librustc_target/spec/mipsel_sony_psp_linker_script.ld diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs new file mode 100644 index 0000000000000..d5765f01ba34a --- /dev/null +++ b/src/librustc_target/spec/mipsel_sony_psp.rs @@ -0,0 +1,59 @@ +use std::{io, fs, env, path::PathBuf}; +use crate::spec::{LinkerFlavor, LldFlavor, LinkArgs, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; + +// The PSP has custom linker requirements. +const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld"); + +fn write_script() -> io::Result { + let path = env::temp_dir().join("rustc-mipsel-sony-psp-linkfile.ld"); + fs::write(&path, LINKER_SCRIPT)?; + Ok(path) +} + +pub fn target() -> TargetResult { + let script = write_script().map_err(|e| { + format!("failed to write link script: {}", e) + })?; + + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert( + LinkerFlavor::Lld(LldFlavor::Ld), + vec![ + "--eh-frame-hdr".to_string(), + "--emit-relocs".to_string(), + "--script".to_string(), + script.display().to_string(), + ], + ); + + Ok(Target { + llvm_target: "mipsel-sony-psp".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), + arch: "mips".to_string(), + target_os: "psp".to_string(), + target_env: "".to_string(), + target_vendor: "sony".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + cpu: "mips2".to_string(), + executables: true, + linker: Some("rust-lld".to_owned()), + relocation_model: RelocModel::Static, + + // PSP FPU only supports single precision floats. + features: "+single-float".to_string(), + + // PSP does not support trap-on-condition instructions. + llvm_args: vec![ + "-mno-check-zero-division".to_string(), + ], + pre_link_args, + ..Default::default() + }, + }) +} diff --git a/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld new file mode 100644 index 0000000000000..9dd38f5ce919c --- /dev/null +++ b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2005 adresd + * Copyright (c) 2005 Marcus R. Brown + * Copyright (c) 2005 James Forshaw + * Copyright (c) 2005 John Kelley + * Copyright (c) 2005 Jesper Svennevid + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +OUTPUT_ARCH(mips:allegrex) +ENTRY(module_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = 0x0); . = 0x0; + .interp : { *(.interp) } + .dynamic : { *(.dynamic) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + /* PSP-specific relocations. */ + .rel.sceStub.text : { *(.rel.sceStub.text) *(SORT(.rel.sceStub.text.*)) } + .rel.lib.ent.top : { *(.rel.lib.ent.top) } + .rel.lib.ent : { *(.rel.lib.ent) } + .rel.lib.ent.btm : { *(.rel.lib.ent.btm) } + .rel.lib.stub.top : { *(.rel.lib.stub.top) } + .rel.lib.stub : { *(.rel.lib.stub) } + .rel.lib.stub.btm : { *(.rel.lib.stub.btm) } + .rel.rodata.sceModuleInfo : { *(.rel.rodata.sceModuleInfo) } + .rel.rodata.sceResident : { *(.rel.rodata.sceResident) } + .rel.rodata.sceNid : { *(.rel.rodata.sceNid) *(SORT(.rel.rodata.sceNid.*)) } + .rel.rodata.sceVstub : { *(.rel.rodata.sceVstub) *(SORT(.rel.rodata.sceVstub.*)) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rel.data.rel.ro : { *(.rel.data.rel.ro*) } + .rela.data.rel.ro : { *(.rel.data.rel.ro*) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) } + .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) } + .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) } + .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) } + .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) } + .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) } + .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) } + .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + + /* Start the text section at 0x0 for PRX generation */ + . = 0; + + .text : + { + _ftext = . ; + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.mips16.fn.*) *(.mips16.call.*) + } =0 + .init : + { + KEEP (*(.init)) + } =0 + .plt : { *(.plt) } + .fini : + { + KEEP (*(.fini)) + } =0 + /* PSP library stub functions. */ + .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + /* PSP library entry table and library stub table. */ + .lib.ent.top : { *(.lib.ent.top) } + .lib.ent : { *(.lib.ent) } + .lib.ent.btm : { *(.lib.ent.btm) } + .lib.stub.top : { *(.lib.stub.top) } + .lib.stub : { *(.lib.stub) } + .lib.stub.btm : { *(.lib.stub.btm) } + /* PSP read-only data for module info, NIDs, and Vstubs. The + .rodata.sceModuleInfo section must appear before the .rodata section + otherwise it would get absorbed into .rodata and the PSP bootloader + would be unable to locate the module info structure. */ + .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) } + .rodata.sceResident : { *(.rodata.sceResident) } + .rodata.sceNid : { KEEP(*(.rodata.sceNid)) KEEP(*(SORT(.rodata.sceNid.*))) } + .rodata.sceVstub : { *(.rodata.sceVstub) *(SORT(.rodata.sceVstub.*)) } + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } + + /* Exception handling */ + .eh_frame_hdr : + { + KEEP(*(.eh_frame_hdr)) + } + + __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; + __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; + + .eh_frame : + { + __eh_frame_start = .; + KEEP(*(.eh_frame)) + __eh_frame_end = .; + } + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(256) + (. & (256 - 1)); + + .gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { KEEP (*(.preinit_array)) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { KEEP (*(.init_array)) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { KEEP (*(.fini_array)) } + PROVIDE (__fini_array_end = .); + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin*.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin*.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) } + .data : + { + _fdata = . ; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + . = .; + _gp = ALIGN(16) + 0x7ff0; + .got : { *(.got.plt) *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + _fbss = .; + .sbss : + { + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + } + . = ALIGN(32 / 8); + _end = .; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.comment) *(.pdr) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 51dce9e144caa..dab1e51e3f872 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -582,6 +582,8 @@ supported_targets! { ("powerpc-wrs-vxworks", powerpc_wrs_vxworks), ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe), ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks), + + ("mipsel-sony-psp", mipsel_sony_psp), } /// Everything `rustc` knows about how to compile for a specific target. From 20a66913233589208934d155491c75157947e03e Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sat, 9 May 2020 16:03:40 -0400 Subject: [PATCH 2/7] Update stdarch --- src/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdarch b/src/stdarch index d10eefc62284c..ec6fccd34c300 160000 --- a/src/stdarch +++ b/src/stdarch @@ -1 +1 @@ -Subproject commit d10eefc62284c40c5a95a2eed19fc1f414a5364d +Subproject commit ec6fccd34c30003a7ebf4e7a9dfe4e31f5b76e1b From 8961b083762d3660ca21110836b547e8b3f19022 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sat, 9 May 2020 16:39:45 -0400 Subject: [PATCH 3/7] Formatting --- src/librustc_target/spec/mipsel_sony_psp.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs index d5765f01ba34a..80c253b86bbd9 100644 --- a/src/librustc_target/spec/mipsel_sony_psp.rs +++ b/src/librustc_target/spec/mipsel_sony_psp.rs @@ -1,6 +1,6 @@ -use std::{io, fs, env, path::PathBuf}; -use crate::spec::{LinkerFlavor, LldFlavor, LinkArgs, RelocModel}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel}; use crate::spec::{Target, TargetOptions, TargetResult}; +use std::{env, fs, io, path::PathBuf}; // The PSP has custom linker requirements. const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld"); @@ -12,9 +12,7 @@ fn write_script() -> io::Result { } pub fn target() -> TargetResult { - let script = write_script().map_err(|e| { - format!("failed to write link script: {}", e) - })?; + let script = write_script().map_err(|e| format!("failed to write link script: {}", e))?; let mut pre_link_args = LinkArgs::new(); pre_link_args.insert( @@ -49,9 +47,7 @@ pub fn target() -> TargetResult { features: "+single-float".to_string(), // PSP does not support trap-on-condition instructions. - llvm_args: vec![ - "-mno-check-zero-division".to_string(), - ], + llvm_args: vec!["-mno-check-zero-division".to_string()], pre_link_args, ..Default::default() }, From 7e62240801cc5f7aa70300fb0f92f54370eabea6 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sun, 10 May 2020 16:06:33 -0400 Subject: [PATCH 4/7] Add lld_link_script to TargetOptions --- src/librustc_codegen_ssa/back/link.rs | 31 +++++++++++++++++++++ src/librustc_target/spec/mipsel_sony_psp.rs | 17 ++--------- src/librustc_target/spec/mod.rs | 6 ++++ 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 7a0e1e2c63887..ab59a1c5f4879 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1179,6 +1179,34 @@ fn add_pre_link_args( cmd.args(&sess.opts.debugging_opts.pre_link_args); } +/// Add an LLD link script embedded in the target, if applicable. +fn add_lld_link_script( + cmd: &mut dyn Linker, + sess: &Session, + flavor: LinkerFlavor, + tmpdir: &Path, + crate_type: CrateType, +) { + match (flavor, crate_type, &sess.target.target.options.lld_link_script) { + ( + LinkerFlavor::Lld(LldFlavor::Ld), + CrateType::Cdylib | CrateType::Executable, + Some(script), + ) => { + let file_name = ["rustc", &sess.target.target.llvm_target, "linkfile.ld"].join("-"); + + let path = tmpdir.join(file_name); + if let Err(e) = fs::write(&path, script) { + sess.fatal(&format!("failed to write link script to {}: {}", path.display(), e)); + } + + cmd.arg("--script"); + cmd.arg(path); + } + _ => {} + } +} + /// Add arbitrary "user defined" args defined from command line and by `#[link_args]` attributes. /// FIXME: Determine where exactly these args need to be inserted. fn add_user_defined_link_args( @@ -1421,6 +1449,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT add_pre_link_args(cmd, sess, flavor, crate_type); + // NO-OPT-OUT + add_lld_link_script(cmd, sess, flavor, tmpdir, crate_type); + // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER if sess.target.target.options.is_like_fuchsia { let prefix = match sess.opts.debugging_opts.sanitizer { diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs index 80c253b86bbd9..eb38dee63b68f 100644 --- a/src/librustc_target/spec/mipsel_sony_psp.rs +++ b/src/librustc_target/spec/mipsel_sony_psp.rs @@ -1,28 +1,14 @@ use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel}; use crate::spec::{Target, TargetOptions, TargetResult}; -use std::{env, fs, io, path::PathBuf}; // The PSP has custom linker requirements. const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld"); -fn write_script() -> io::Result { - let path = env::temp_dir().join("rustc-mipsel-sony-psp-linkfile.ld"); - fs::write(&path, LINKER_SCRIPT)?; - Ok(path) -} - pub fn target() -> TargetResult { - let script = write_script().map_err(|e| format!("failed to write link script: {}", e))?; - let mut pre_link_args = LinkArgs::new(); pre_link_args.insert( LinkerFlavor::Lld(LldFlavor::Ld), - vec![ - "--eh-frame-hdr".to_string(), - "--emit-relocs".to_string(), - "--script".to_string(), - script.display().to_string(), - ], + vec!["--eh-frame-hdr".to_string(), "--emit-relocs".to_string()], ); Ok(Target { @@ -49,6 +35,7 @@ pub fn target() -> TargetResult { // PSP does not support trap-on-condition instructions. llvm_args: vec!["-mno-check-zero-division".to_string()], pre_link_args, + lld_link_script: Some(LINKER_SCRIPT.to_string()), ..Default::default() }, }) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index dab1e51e3f872..91dfa1550f626 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -668,6 +668,9 @@ pub struct TargetOptions { /// Linker arguments that are unconditionally passed *after* any /// user-defined libraries. pub post_link_args: LinkArgs, + /// Optional LLD link script applied to `dylib` and `executable` crate + /// types. This is a string containing the script, not a path. + pub lld_link_script: Option, /// Environment variables to be set for the linker invocation. pub link_env: Vec<(String, String)>, @@ -897,6 +900,7 @@ impl Default for TargetOptions { pre_link_args: LinkArgs::new(), pre_link_args_crt: LinkArgs::new(), post_link_args: LinkArgs::new(), + lld_link_script: None, asm_args: Vec::new(), cpu: "generic".to_string(), features: String::new(), @@ -1246,6 +1250,7 @@ impl Target { key!(post_link_objects, list); key!(post_link_objects_crt, list); key!(post_link_args, link_args); + key!(lld_link_script, optional); key!(link_env, env); key!(link_env_remove, list); key!(asm_args, list); @@ -1475,6 +1480,7 @@ impl ToJson for Target { target_option_val!(post_link_objects); target_option_val!(post_link_objects_crt); target_option_val!(link_args - post_link_args); + target_option_val!(lld_link_script); target_option_val!(env - link_env); target_option_val!(link_env_remove); target_option_val!(asm_args); From 7b649c7364f5128da33c34573a158477df030b70 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sun, 10 May 2020 17:39:57 -0400 Subject: [PATCH 5/7] Renamed lld_link_script to link_script and support all GNU-like linkers --- src/librustc_codegen_ssa/back/link.rs | 19 +++++++++---------- src/librustc_target/spec/mipsel_sony_psp.rs | 3 ++- src/librustc_target/spec/mod.rs | 13 +++++++------ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index ab59a1c5f4879..dca9f12df09b3 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1179,20 +1179,19 @@ fn add_pre_link_args( cmd.args(&sess.opts.debugging_opts.pre_link_args); } -/// Add an LLD link script embedded in the target, if applicable. -fn add_lld_link_script( +/// Add a link script embedded in the target, if applicable. +fn add_link_script( cmd: &mut dyn Linker, sess: &Session, - flavor: LinkerFlavor, tmpdir: &Path, crate_type: CrateType, ) { - match (flavor, crate_type, &sess.target.target.options.lld_link_script) { - ( - LinkerFlavor::Lld(LldFlavor::Ld), - CrateType::Cdylib | CrateType::Executable, - Some(script), - ) => { + match (crate_type, &sess.target.target.options.link_script) { + (CrateType::Cdylib | CrateType::Executable, Some(script)) => { + if !sess.target.target.options.linker_is_gnu { + sess.fatal("can only use link script when linking with GNU-like linker"); + } + let file_name = ["rustc", &sess.target.target.llvm_target, "linkfile.ld"].join("-"); let path = tmpdir.join(file_name); @@ -1450,7 +1449,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( add_pre_link_args(cmd, sess, flavor, crate_type); // NO-OPT-OUT - add_lld_link_script(cmd, sess, flavor, tmpdir, crate_type); + add_link_script(cmd, sess, tmpdir, crate_type); // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER if sess.target.target.options.is_like_fuchsia { diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs index eb38dee63b68f..0c74454d0c5fe 100644 --- a/src/librustc_target/spec/mipsel_sony_psp.rs +++ b/src/librustc_target/spec/mipsel_sony_psp.rs @@ -27,6 +27,7 @@ pub fn target() -> TargetResult { cpu: "mips2".to_string(), executables: true, linker: Some("rust-lld".to_owned()), + linker_is_gnu: true, relocation_model: RelocModel::Static, // PSP FPU only supports single precision floats. @@ -35,7 +36,7 @@ pub fn target() -> TargetResult { // PSP does not support trap-on-condition instructions. llvm_args: vec!["-mno-check-zero-division".to_string()], pre_link_args, - lld_link_script: Some(LINKER_SCRIPT.to_string()), + link_script: Some(LINKER_SCRIPT.to_string()), ..Default::default() }, }) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 91dfa1550f626..00088a0d0404a 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -668,9 +668,10 @@ pub struct TargetOptions { /// Linker arguments that are unconditionally passed *after* any /// user-defined libraries. pub post_link_args: LinkArgs, - /// Optional LLD link script applied to `dylib` and `executable` crate - /// types. This is a string containing the script, not a path. - pub lld_link_script: Option, + /// Optional link script applied to `dylib` and `executable` crate types. + /// This is a string containing the script, not a path. Can only be applied + /// to linkers where `linker_is_gnu` is true. + pub link_script: Option, /// Environment variables to be set for the linker invocation. pub link_env: Vec<(String, String)>, @@ -900,7 +901,7 @@ impl Default for TargetOptions { pre_link_args: LinkArgs::new(), pre_link_args_crt: LinkArgs::new(), post_link_args: LinkArgs::new(), - lld_link_script: None, + link_script: None, asm_args: Vec::new(), cpu: "generic".to_string(), features: String::new(), @@ -1250,7 +1251,7 @@ impl Target { key!(post_link_objects, list); key!(post_link_objects_crt, list); key!(post_link_args, link_args); - key!(lld_link_script, optional); + key!(link_script, optional); key!(link_env, env); key!(link_env_remove, list); key!(asm_args, list); @@ -1480,7 +1481,7 @@ impl ToJson for Target { target_option_val!(post_link_objects); target_option_val!(post_link_objects_crt); target_option_val!(link_args - post_link_args); - target_option_val!(lld_link_script); + target_option_val!(link_script); target_option_val!(env - link_env); target_option_val!(link_env_remove); target_option_val!(asm_args); From 744449433004fbdc3d0d665551e59ca2880f0552 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sun, 10 May 2020 17:53:04 -0400 Subject: [PATCH 6/7] Run rustfmt --- src/librustc_codegen_ssa/back/link.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index dca9f12df09b3..ca2d1b0488da6 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1180,12 +1180,7 @@ fn add_pre_link_args( } /// Add a link script embedded in the target, if applicable. -fn add_link_script( - cmd: &mut dyn Linker, - sess: &Session, - tmpdir: &Path, - crate_type: CrateType, -) { +fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) { match (crate_type, &sess.target.target.options.link_script) { (CrateType::Cdylib | CrateType::Executable, Some(script)) => { if !sess.target.target.options.linker_is_gnu { From 425723f5b384ba75af4b9a6b4e0186f8bf2e99a3 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Thu, 14 May 2020 06:19:36 -0400 Subject: [PATCH 7/7] Rewrite link script from scratch This absolves previous licensing issues. --- .../spec/mipsel_sony_psp_linker_script.ld | 297 ++---------------- 1 file changed, 21 insertions(+), 276 deletions(-) diff --git a/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld index 9dd38f5ce919c..1bd436d6f94cc 100644 --- a/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld +++ b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld @@ -1,151 +1,24 @@ -/* - * Copyright (c) 2005 adresd - * Copyright (c) 2005 Marcus R. Brown - * Copyright (c) 2005 James Forshaw - * Copyright (c) 2005 John Kelley - * Copyright (c) 2005 Jesper Svennevid - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -OUTPUT_ARCH(mips:allegrex) ENTRY(module_start) SECTIONS { - /* Read-only sections, merged into text segment: */ - PROVIDE (__executable_start = 0x0); . = 0x0; - .interp : { *(.interp) } - .dynamic : { *(.dynamic) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } - .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } - .rel.init : { *(.rel.init) } - .rela.init : { *(.rela.init) } - .rel.fini : { *(.rel.fini) } - .rela.fini : { *(.rela.fini) } - /* PSP-specific relocations. */ - .rel.sceStub.text : { *(.rel.sceStub.text) *(SORT(.rel.sceStub.text.*)) } - .rel.lib.ent.top : { *(.rel.lib.ent.top) } - .rel.lib.ent : { *(.rel.lib.ent) } - .rel.lib.ent.btm : { *(.rel.lib.ent.btm) } - .rel.lib.stub.top : { *(.rel.lib.stub.top) } - .rel.lib.stub : { *(.rel.lib.stub) } - .rel.lib.stub.btm : { *(.rel.lib.stub.btm) } - .rel.rodata.sceModuleInfo : { *(.rel.rodata.sceModuleInfo) } - .rel.rodata.sceResident : { *(.rel.rodata.sceResident) } - .rel.rodata.sceNid : { *(.rel.rodata.sceNid) *(SORT(.rel.rodata.sceNid.*)) } - .rel.rodata.sceVstub : { *(.rel.rodata.sceVstub) *(SORT(.rel.rodata.sceVstub.*)) } - .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } - .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } - .rel.data.rel.ro : { *(.rel.data.rel.ro*) } - .rela.data.rel.ro : { *(.rel.data.rel.ro*) } - .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } - .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } - .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } - .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } - .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } - .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } - .rel.ctors : { *(.rel.ctors) } - .rela.ctors : { *(.rela.ctors) } - .rel.dtors : { *(.rel.dtors) } - .rela.dtors : { *(.rela.dtors) } - .rel.got : { *(.rel.got) } - .rela.got : { *(.rela.got) } - .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) } - .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) } - .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) } - .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) } - .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) } - .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) } - .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) } - .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) } - .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } - .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - - /* Start the text section at 0x0 for PRX generation */ - . = 0; - - .text : - { - _ftext = . ; - *(.text .stub .text.* .gnu.linkonce.t.*) - KEEP (*(.text.*personality*)) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.mips16.fn.*) *(.mips16.call.*) - } =0 - .init : - { - KEEP (*(.init)) - } =0 - .plt : { *(.plt) } - .fini : - { - KEEP (*(.fini)) - } =0 - /* PSP library stub functions. */ - .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) } - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - /* PSP library entry table and library stub table. */ - .lib.ent.top : { *(.lib.ent.top) } - .lib.ent : { *(.lib.ent) } - .lib.ent.btm : { *(.lib.ent.btm) } - .lib.stub.top : { *(.lib.stub.top) } - .lib.stub : { *(.lib.stub) } - .lib.stub.btm : { *(.lib.stub.btm) } - /* PSP read-only data for module info, NIDs, and Vstubs. The - .rodata.sceModuleInfo section must appear before the .rodata section - otherwise it would get absorbed into .rodata and the PSP bootloader - would be unable to locate the module info structure. */ - .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) } - .rodata.sceResident : { *(.rodata.sceResident) } - .rodata.sceNid : { KEEP(*(.rodata.sceNid)) KEEP(*(SORT(.rodata.sceNid.*))) } - .rodata.sceVstub : { *(.rodata.sceVstub) *(SORT(.rodata.sceVstub.*)) } - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } - .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } - .gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } - - /* Exception handling */ - .eh_frame_hdr : - { - KEEP(*(.eh_frame_hdr)) - } - + /* PRX format requires text to begin at 0 */ + .text 0 : { *(.text .text.*) } + + /* Sort stubs for convenient ordering */ + .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) } + + /* Keep these sections around, even though they may appear unused to the linker */ + .lib.ent.top : { KEEP(*(.lib.ent.top)) } + .lib.ent : { KEEP(*(.lib.ent)) } + .lib.ent.btm : { KEEP(*(.lib.ent.btm)) } + .lib.stub.top : { KEEP(*(.lib.stub.top)) } + .lib.stub : { KEEP(*(.lib.stub)) } + .lib.stub.btm : { KEEP(*(.lib.stub.btm)) } + .eh_frame_hdr : { KEEP(*(.eh_frame_hdr)) } + + /* Add symbols for LLVM's libunwind */ __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; - .eh_frame : { __eh_frame_start = .; @@ -153,137 +26,9 @@ SECTIONS __eh_frame_end = .; } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN(256) + (. & (256 - 1)); - - .gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } - /* Thread Local Storage sections */ - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - /* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ - . = ALIGN(32 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { KEEP (*(.preinit_array)) } - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : { KEEP (*(.init_array)) } - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : { KEEP (*(.fini_array)) } - PROVIDE (__fini_array_end = .); - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin*.o(.ctors)) - /* We don't want to include the .ctor section from - from the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } - .dtors : - { - KEEP (*crtbegin*.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } - .jcr : { KEEP (*(.jcr)) } - .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) } - .data : - { - _fdata = . ; - *(.data .data.* .gnu.linkonce.d.*) - KEEP (*(.gnu.linkonce.d.*personality*)) - SORT(CONSTRUCTORS) - } - .data1 : { *(.data1) } - . = .; - _gp = ALIGN(16) + 0x7ff0; - .got : { *(.got.plt) *(.got) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : - { - *(.sdata .sdata.* .gnu.linkonce.s.*) - } - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - _edata = .; - PROVIDE (edata = .); - __bss_start = .; - _fbss = .; - .sbss : - { - PROVIDE (__sbss_start = .); - PROVIDE (___sbss_start = .); - *(.dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - PROVIDE (__sbss_end = .); - PROVIDE (___sbss_end = .); - } - .bss : - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. */ - . = ALIGN(32 / 8); - } - . = ALIGN(32 / 8); - _end = .; - PROVIDE (end = .); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /DISCARD/ : { *(.comment) *(.pdr) } - /DISCARD/ : { *(.note.GNU-stack) } + /* These are explicitly listed to avoid being merged into .rodata */ + .rodata.sceResident : { *(.rodata.sceResident) } + .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) } + /* Sort NIDs for convenient ordering */ + .rodata.sceNid : { *(.rodata.sceNid) *(SORT(.rodata.sceNid.*)) } }