diff --git a/cmake/recipes/BuildHostDependencies.cmake b/cmake/recipes/BuildHostDependencies.cmake index e9e5b74..365217d 100644 --- a/cmake/recipes/BuildHostDependencies.cmake +++ b/cmake/recipes/BuildHostDependencies.cmake @@ -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" diff --git a/cmake/recipes/BuildSdkComponents.cmake b/cmake/recipes/BuildSdkComponents.cmake index 84d0d83..98bea63 100644 --- a/cmake/recipes/BuildSdkComponents.cmake +++ b/cmake/recipes/BuildSdkComponents.cmake @@ -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 diff --git a/cmake/recipes/GccCommonArgs.cmake b/cmake/recipes/GccCommonArgs.cmake index 82e7c0a..b193e63 100644 --- a/cmake/recipes/GccCommonArgs.cmake +++ b/cmake/recipes/GccCommonArgs.cmake @@ -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 @@ -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 diff --git a/patches/binutils/0006-tls-in-rodata-segment.patch b/patches/binutils/0006-tls-in-rodata-segment.patch new file mode 100644 index 0000000..e092b59 --- /dev/null +++ b/patches/binutils/0006-tls-in-rodata-segment.patch @@ -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 <.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. diff --git a/patches/gcc/0001-vita-target.patch b/patches/gcc/0001-vita-target.patch index 7809936..b49f43d 100644 --- a/patches/gcc/0001-vita-target.patch +++ b/patches/gcc/0001-vita-target.patch @@ -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 @@ -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 diff --git a/patches/gcc/0005-libstdcxx-cxa-thread-atexit.patch b/patches/gcc/0005-libstdcxx-cxa-thread-atexit.patch new file mode 100644 index 0000000..259388d --- /dev/null +++ b/patches/gcc/0005-libstdcxx-cxa-thread-atexit.patch @@ -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 + +