Files
Steam-Link-PS5/tooling/native/ps5-pie.ld
T
jmelovich d3049b4bc6 M1: ihslib, protobuf-c, mbedtls, opus and libc++ cross-built; the title discovers Steam
tools/build-deps.sh builds the streaming stack once into build/deps from explicit
file lists (ihslib's CMake wants pkg-config and SDL2). platform/ps5 holds the
pthread backend for ihslib, ProsperoLight's sceNet socket adapter and entropy
source, and an __assert shim. The app links the SDK's libc++/libc++abi/libunwind
(the linker script now brackets .eh_frame for libunwind; -L satisfies libc++'s
pthread dependent-library note with the SDK's empty libpthread.a).

src/main.cpp drives discovery, PIN pairing and the streaming request from a flow
thread and counts delivered video/audio frames; app_storage keeps the identity and
log under /data/steamlink-ps5.

Tested on the console: discovers the PC in 3 s, unauthorized stream request leads to
the pairing prompt with a PIN on screen.
2026-10-08 17:24:28 -07:00

86 lines
2.6 KiB
Plaintext

/*
* ps5-native-app-boilerplate - Intermediate PIE linker layout.
* Copyright (C) 2026 BlackBearReloaded
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Keeps code, immutable data, RELRO, and writable data in distinct address
* ranges. The native converter replaces LLVM's generic dynamic metadata.
*/
OUTPUT_FORMAT("elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
PHDRS {
text PT_LOAD FLAGS (0x5);
ro PT_LOAD FLAGS (0x4);
relro PT_LOAD FLAGS (0x6);
data PT_LOAD FLAGS (0x6);
dynamic PT_DYNAMIC FLAGS (0x6);
}
SECTIONS {
.text 0 : ALIGN(CONSTANT(MAXPAGESIZE)) {
QUAD(0xcccccccccccccccc)
QUAD(0xcccccccccccccccc)
*(.text .text.*)
*(.plt .plt.*)
} : text
/* The bracket symbols are what libunwind (pulled in by libc++abi) looks up. */
.eh_frame_hdr : ALIGN(CONSTANT(MAXPAGESIZE)) {
PROVIDE_HIDDEN(__eh_frame_hdr_start = .);
KEEP(*(.eh_frame_hdr))
PROVIDE_HIDDEN(__eh_frame_hdr_end = .);
} : ro
.eh_frame : {
PROVIDE_HIDDEN(__eh_frame_start = .);
KEEP(*(.eh_frame))
PROVIDE_HIDDEN(__eh_frame_end = .);
} : ro
.gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } : ro
.rodata : { *(.rodata .rodata.*) } : ro
. = ALIGN(CONSTANT(MAXPAGESIZE));
.data.rel.ro : {
*(.data.rel.ro .data.rel.ro.*)
} : relro
.got : { *(.got) } : relro
.got.plt : { *(.got.plt) } : relro
.preinit_array : {
PROVIDE_HIDDEN(__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN(__preinit_array_end = .);
} : relro
.init_array : {
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP(*(.init_array .ctors))
PROVIDE_HIDDEN(__init_array_end = .);
} : relro
.fini_array : {
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP(*(.fini_array .dtors))
PROVIDE_HIDDEN(__fini_array_end = .);
} : relro
/* Kept only long enough for the converter to read and rewrite them. */
.dynsym : { *(.dynsym) } : relro
.gnu.hash : { *(.gnu.hash) } : relro
.dynstr : { *(.dynstr) } : relro
.rela.dyn : { *(.rela.dyn) } : relro
.rela.plt : { *(.rela.plt) } : relro
. = ALIGN(CONSTANT(MAXPAGESIZE));
.dynamic : {
*(.dynamic)
} : data : dynamic
.data : { *(.data .data.*) } : data
.tdata : { *(.tdata .tdata.*) } : data
.tbss : { *(.tbss .tbss.*) } : data
.bss : {
*(.bss .bss.*)
*(COMMON)
} : data
}