Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmake/recipes/BuildHostDependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ function(toolchain_deps toolchain_deps_dir toolchain_install_dir toolchain_suffi
"${PROJECT_SOURCE_DIR}/patches/binutils/0002-fix-broken-reloc.patch|1"
"${PROJECT_SOURCE_DIR}/patches/binutils/0003-fix-elf-vaddr.patch|1"
"${PROJECT_SOURCE_DIR}/patches/binutils/0004-fix-interworking-veneers.patch|1"
"${PROJECT_SOURCE_DIR}/patches/binutils/0005-genscripts-mkdir.patch|1")
"${PROJECT_SOURCE_DIR}/patches/binutils/0005-genscripts-mkdir.patch|1"
"${PROJECT_SOURCE_DIR}/patches/binutils/0006-tls-in-rodata-segment.patch|1"
"${PROJECT_SOURCE_DIR}/patches/binutils/0007-tls-tcb-size-per-emulation.patch|1")
set(gdb_patch_series
"${PROJECT_SOURCE_DIR}/patches/gdb.patch|1"
"${PROJECT_SOURCE_DIR}/patches/gdb-zlib.patch|1"
Expand Down
1 change: 1 addition & 0 deletions cmake/recipes/BuildSdkComponents.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ ExternalProject_Add(newlib
# Multibyte/UTF-8: sin esto setlocale queda clavado en US-ASCII y toda la
# familia mbrtowc/wcrtomb es inoperante (descubierto con musl libc-test)
--enable-newlib-mb
--enable-newlib-reent-thread-local
BUILD_COMMAND ${compiler_flags} ${toolchain_tools} ${wrapper_command} $(MAKE)
INSTALL_COMMAND $(MAKE) install DESTDIR=${CMAKE_INSTALL_PREFIX}
# Save the commit id for tracking purposes
Expand Down
5 changes: 3 additions & 2 deletions cmake/recipes/GccCommonArgs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ set(gcc_patch_series
"${PROJECT_SOURCE_DIR}/patches/gcc/0001-vita-target.patch|1"
"${PROJECT_SOURCE_DIR}/patches/gcc/0002-vita-driver.patch|1"
"${PROJECT_SOURCE_DIR}/patches/gcc/0003-libgomp-vita.patch|1"
"${PROJECT_SOURCE_DIR}/patches/gcc/0004-host-compat.patch|1")
"${PROJECT_SOURCE_DIR}/patches/gcc/0004-host-compat.patch|1"
"${PROJECT_SOURCE_DIR}/patches/gcc/0005-libstdcxx-cxa-thread-atexit.patch|1")
list(JOIN gcc_patch_series "^" gcc_patch_series_arg)
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
# GCC on OSX (Clang in diguise) needs more bracket nesting depth to compile gcc
Expand All @@ -36,7 +37,7 @@ set(common_gcc_configure_args
--disable-libstdcxx-pch
--disable-nls
--disable-shared
--disable-tls
--enable-tls
--with-gnu-as
--with-gnu-ld
--with-newlib
Expand Down
64 changes: 64 additions & 0 deletions patches/binutils/0006-tls-in-rodata-segment.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -729,6 +729,27 @@
${TEXT_PLT+${PLT_NEXT_DATA+${PLT} ${OTHER_PLT_SECTIONS}}}
EOF

+if [ -n "${TLS_IN_RODATA}" ]; then
+cat <<EOF
+ /* Thread Local Storage sections. Kept in the read-only segment (not with
+ .data below): the loader only ever reads .tdata to build each thread's
+ TLS block, it's never written in place, and this target's module
+ metadata encodes tls_start as an offset relative to the same segment
+ as the entry point/module info - keeping them together avoids ever
+ needing an offset that crosses into a different segment.
+ (READONLY) drops SHF_WRITE from these output sections (bfd/elf.c
+ only sets it when SEC_READONLY is absent) so the enclosing PT_LOAD
+ doesn't inherit a spurious write flag from otherwise-never-written
+ TLS template data. Set by TLS_IN_RODATA in the emulparams file. */
+ .tdata ${RELOCATING-0} (READONLY) :
+ {
+ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN ($(def_symbol "__tdata_start"));}}
+ *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*})
+ }
+ .tbss ${RELOCATING-0} (READONLY) : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
+EOF
+fi
+
test -n "${RELOCATING}" && cat <<EOF
/* Various note sections. Placed here so that they are always included
in the read-only segment and not treated as orphan sections. The
@@ -802,7 +823,10 @@
.gnu_extab ${RELOCATING-0} : ONLY_IF_RW { *(.gnu_extab) }
.gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table${RELOCATING+ .gcc_except_table.*}) }
.exception_ranges ${RELOCATING-0} : ONLY_IF_RW { *(.exception_ranges${RELOCATING+*}) }
+EOF

+if [ -z "${TLS_IN_RODATA}" ]; then
+cat <<EOF
/* Thread Local Storage sections. */
.tdata ${RELOCATING-0} :
{
@@ -810,7 +834,10 @@
*(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*})
}
.tbss ${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
+EOF
+fi

+cat <<EOF
${RELOCATING+$(emit_init_fini_arrays)}

${SMALL_DATA_CTOR-${RELOCATING+${CTOR}}}
diff --git a/ld/emulparams/armvita.sh b/ld/emulparams/armvita.sh
--- a/ld/emulparams/armvita.sh
+++ b/ld/emulparams/armvita.sh
@@ -3,3 +3,7 @@
TEXT_START_ADDR=0x81000000
MAXPAGESIZE="0x10000"
COMMONPAGESIZE="0x10000"
+# module_info's tls_start is an offset relative to the same segment as the
+# entry point (see vita-toolchain's sce-elf.c) - keep .tdata/.tbss in the
+# read-only segment, alongside it, instead of the default writable one.
+TLS_IN_RODATA=yes
100 changes: 100 additions & 0 deletions patches/binutils/0007-tls-tcb-size-per-emulation.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h
--- a/bfd/elf32-arm.h
+++ b/bfd/elf32-arm.h
@@ -84,6 +84,12 @@
int merge_exidx_entries;
int cmse_implib;
bfd *in_implib_bfd;
+ /* Size of the reserved thread control block ahead of TP in the Local
+ Exec TLS model. 8 on every mainstream ARM EABI target (glibc/newlib's
+ usual "Variant 1" layout); some bare-metal targets place their TLS
+ block directly at the thread pointer instead and need this to be 0.
+ Per-emulation, set via ld/emulparams/<emu>.sh's TCB_SIZE. */
+ int tcb_size;
};

void bfd_elf32_arm_set_target_params
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -3046,8 +3046,6 @@
bool non_a8_stub;
};

-/* The size of the thread control block. */
-#define TCB_SIZE 8

/* ARM-specific information about a PLT entry, over and above the usual
gotplt_union. */
@@ -3385,6 +3383,12 @@
/* True if the target system uses FDPIC. */
int fdpic_p;

+ /* Size of the reserved TCB ahead of the thread pointer for the Local
+ Exec TLS model - see struct elf32_arm_params::tcb_size. Defaults to
+ the standard ARM EABI value of 8; set from ld via
+ bfd_elf32_arm_set_target_params. */
+ bfd_vma tcb_size;
+
/* Fixup section. Used for FDPIC. */
asection *srofixup;
};
@@ -4057,6 +4061,7 @@
ret->use_rel = true;
ret->obfd = abfd;
ret->fdpic_p = 0;
+ ret->tcb_size = 8;

if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc,
sizeof (struct elf32_arm_stub_hash_entry)))
@@ -9030,6 +9035,7 @@
globals->fix_arm1176 = params->fix_arm1176;
globals->cmse_implib = params->cmse_implib;
globals->in_implib_bfd = params->in_implib_bfd;
+ globals->tcb_size = (bfd_vma) params->tcb_size;

BFD_ASSERT (is_arm_elf (output_bfd));
elf_arm_tdata (output_bfd)->no_enum_size_warning
@@ -9940,12 +9946,13 @@
tpoff (struct bfd_link_info *info, bfd_vma address)
{
struct elf_link_hash_table *htab = elf_hash_table (info);
+ struct elf32_arm_link_hash_table *arm_htab = elf32_arm_hash_table (info);
bfd_vma base;

/* If tls_sec is NULL, we should have signalled an error already. */
if (htab->tls_sec == NULL)
return 0;
- base = align_power ((bfd_vma) TCB_SIZE, htab->tls_sec->alignment_power);
+ base = align_power (arm_htab->tcb_size, htab->tls_sec->alignment_power);
return address - htab->tls_sec->vma + base;
}

diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em
--- a/ld/emultempl/armelf.em
+++ b/ld/emultempl/armelf.em
@@ -46,7 +46,8 @@
1, /* fix_arm1176 */
-1, /* merge_exidx_entries */
0, /* cmse_implib */
- NULL /* in_implib_bfd */
+ NULL, /* in_implib_bfd */
+ ${TCB_SIZE-8} /* tcb_size */
};
static char *in_implib_filename = NULL;

diff --git a/ld/emulparams/armvita.sh b/ld/emulparams/armvita.sh
--- a/ld/emulparams/armvita.sh
+++ b/ld/emulparams/armvita.sh
@@ -3,6 +3,11 @@
TEXT_START_ADDR=0x81000000
MAXPAGESIZE="0x10000"
COMMONPAGESIZE="0x10000"
+# Vita's TPIDRURO points directly at .tdata, no reserved TCB header ahead of
+# it (confirmed on real hardware: the kernel copies the TLS template to
+# TPIDRURO+0, not the ARM EABI "Variant 1" default of TPIDRURO+8). See
+# elf32_arm_params::tcb_size in bfd/elf32-arm.h.
+TCB_SIZE=0
# module_info's tls_start is an offset relative to the same segment as the
# entry point (see vita-toolchain's sce-elf.c) - keep .tdata/.tbss in the
# read-only segment, alongside it, instead of the default writable one.
16 changes: 14 additions & 2 deletions patches/gcc/0001-vita-target.patch
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,19 @@ diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 30e1d6dc9..bd5f7b19c 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -731,6 +731,10 @@ extern const int arm_arch_cde_coproc_bits[];
@@ -87,8 +87,10 @@ extern tree arm_bf16_ptr_type_node;
#undef CPP_SPEC
#define CPP_SPEC "%(subtarget_cpp_spec)"

#ifndef CC1_SPEC
-#define CC1_SPEC ""
+/* The loader hands each thread its TLS block at a fixed offset from
+ TPIDRURO; every model but local-exec wants a GOT it never fills. */
+#define CC1_SPEC "%{!ftls-model=*:-ftls-model=local-exec}"
#endif

/* This macro defines names of additional specifications to put in the specs
@@ -731,6 +733,10 @@ extern const int arm_arch_cde_coproc_bits[];
#define WCHAR_TYPE_SIZE BITS_PER_WORD
#endif

Expand All @@ -26,7 +38,7 @@ index 30e1d6dc9..bd5f7b19c 100644
/* Sized for fixed-point types. */

#define SHORT_FRACT_TYPE_SIZE 8
@@ -1996,7 +2000,7 @@ enum arm_auto_incmodes
@@ -1996,7 +2002,7 @@ enum arm_auto_incmodes
/* signed 'char' is most compatible, but RISC OS wants it unsigned.
unsigned is probably best, but may break some code. */
#ifndef DEFAULT_SIGNED_CHAR
Expand Down
29 changes: 29 additions & 0 deletions patches/gcc/0005-libstdcxx-cxa-thread-atexit.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -339,6 +339,11 @@
# on a hosted environment.
if test "x${with_newlib}" = "xyes"; then
os_include_dir="os/newlib"
+ case "${host}" in
+ arm-vita-eabi*)
+ AC_DEFINE(HAVE___CXA_THREAD_ATEXIT)
+ ;;
+ esac
AC_DEFINE(HAVE_HYPOT)

# GLIBCXX_CHECK_STDLIB_SUPPORT
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -27343,6 +27343,12 @@
# on a hosted environment.
if test "x${with_newlib}" = "xyes"; then
os_include_dir="os/newlib"
+ case "${host}" in
+ arm-vita-eabi*)
+ $as_echo "#define HAVE___CXA_THREAD_ATEXIT 1" >>confdefs.h
+
+ ;;
+ esac
$as_echo "#define HAVE_HYPOT 1" >>confdefs.h


Loading