From b6e4581937dff28f4534e393907124182fb791d0 Mon Sep 17 00:00:00 2001
From: Marko Mijalkovic <marko.mijalkovic97@gmail.com>
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<PathBuf> {
+    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 <marko.mijalkovic97@gmail.com>
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 <marko.mijalkovic97@gmail.com>
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<PathBuf> {
 }
 
 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 <marko.mijalkovic97@gmail.com>
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<PathBuf> {
-    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<String>,
 
     /// 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 <marko.mijalkovic97@gmail.com>
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<String>,
+    /// 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<String>,
 
     /// 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 <marko.mijalkovic97@gmail.com>
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 <marko.mijalkovic97@gmail.com>
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.*)) }
 }