diff --git a/llvm/tools/llvm-libgcc/CMakeLists.txt b/llvm/tools/llvm-libgcc/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/CMakeLists.txt @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 3.13.4) + +# If we are not building as a part of LLVM, build llvm-libgcc as a standalone +# project, using compiler-rt and libunwind external libraries. +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + project(LLVM_LIBGCC) + if(NOT LLVM_LIBGCC_LIBUNWIND_DIR) + message(FATAL_ERROR + "We're building llvm-libgcc as a standalone project, but we didn't " + " supply a path to LLVM_LIBGCC_LIBUNWIND_DIR. It's not possible to build " + "llvm-libgcc without this path!") + endif() +elseif(NOT LLVM_ENABLE_LIBGCC) + return() +endif() + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") + +set(LLVM_LIBGCC_SYSROOT "${CMAKE_INSTALL_PREFIX}" CACHE PATH + "Assumes this path as the root directory when setting symlinks.") + +set(LLVM_LIBGCC_COMPILER_RT_DIR "" CACHE PATH + "Absolute path to a pre-existing compiler-rt builtins.") +find_package(CompilerRT REQUIRED) +string(REGEX REPLACE "^${LLVM_LIBGCC_SYSROOT}/lib${LLVMLIB_DIR_SUFFIX}/*" "" + LLVM_LIBGCC_COMPILER_RT "${LLVM_LIBGCC_COMPILER_RT}") + +set(LLVM_LIBGCC_LIBUNWIND_DIR "" CACHE PATH + "Absolute path to a pre-existing libunwind.a.") +find_package(LLVMLibunwind REQUIRED) +string(REGEX REPLACE "^${LLVM_LIBGCC_SYSROOT}/lib${LLVMLIB_DIR_SUFFIX}/*" "" + LLVM_LIBGCC_UNWIND_STATIC "${LLVM_LIBGCC_UNWIND_STATIC}") + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib${LLVMLIB_DIR_SUFFIX}") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib${LLVMLIB_DIR_SUFFIX}") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib${LLVMLIB_DIR_SUFFIX}") + +add_custom_target( + always_run_target ALL + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gcc_s.ver" +) + +set(LLVM_LIBGCC_PYTHON_SCRIPT "version-scripts/generate_version_script.py") + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/gcc_s.ver" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_LIBGCC_PYTHON_SCRIPT}" + COMMAND python "${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_LIBGCC_PYTHON_SCRIPT}" "--target=${LLVM_DEFAULT_TARGET_TRIPLE}" +) + +add_subdirectory(lib) diff --git a/llvm/tools/llvm-libgcc/FindCompilerRT.cmake b/llvm/tools/llvm-libgcc/FindCompilerRT.cmake new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/FindCompilerRT.cmake @@ -0,0 +1,101 @@ +include(FindPackageHandleStandardArgs) +include(CheckLibraryExists) + +function(building_compiler_rt) + if(LLVM_LIBGCC_COMPILER_RT_DIR) + return() + endif() + + list(FIND LLVM_ENABLE_PROJECTS compiler-rt LLVM_LIBGCC_HAS_COMPILER_RT) + if(NOT LLVM_LIBGCC_HAS_COMPILER_RT) + return() + endif() + + if(NOT COMPILER_RT_BUILD_BUILTINS) + message(SEND_ERROR + "When building llvm-libgcc alongside compiler-rt, we need to set " + "-DCOMPILER_RT_BUILD_BUILTINS=On so we can export all the necessary " + "symbols.") + return() + endif() + + if(NOT COMPILER_RT_BUILTINS_HIDE_SYMBOLS) + message(SEND_ERROR + "When building llvm-libgcc alongside compiler-rt, we need to set " + "-DCOMPILER_RT_BUILTINS_HIDE_SYMBOLS=Off so we can export all the " + "necessary symbols.") + return() + endif() + + set(LLVM_LIBGCC_COMPILER_RT builtins) + set(CompilerRT_FOUND ON) + message(STATUS "llvm-libgcc is using in-tree compiler-rt") +endfunction() + +function(find_external_compiler_rt) + if(NOT ${CMAKE_CHECK_CXX_COMPILER_ID} MATCHES Clang AND + NOT LLVM_LIBGCC_COMPILER_RT_DIR) + message(STATUS + "When building llvm-libgcc without compiler-rt (e.g. as a standalone " + "project), we either need to be using Clang, or " + "'LLVM_LIBGCC_COMPILER_RT_INSTALL_DIRECTORY' must be set to a directory.") + return() + endif() + + if(LLVM_LIBGCC_COMPILER_RT_DIR) + set(LLVM_LIBGCC_PATH_TO_RTLIB + "${LLVM_LIBGCC_COMPILER_RT_DIR}/libclang_rt.builtins.a") + + check_library_exists("${LLVM_LIBGCC_PATH_TO_RTLIB}" emutls_key_destructor + LLVM_LIBGCC_HAS_EXTERNAL_RTLIB) + if (NOT LLVM_LIBGCC_HAS_EXTERNAL_RTLIB) + message(SEND_ERROR + "When using LLVM_LIBGCC_COMPILER_RT_DIR='${LLVM_LIBGCC_COMPILER_RT_DIR}', " + "we couldn't path '${LLVM_LIBGCC_PATH_TO_RTLIB}'. There could be a few " + "reasons for this (e.g. typo in path or wrong permissions for file), " + "and a manual inspection is necessary.") + return() + endif() + + set(LLVM_LIBGCC_COMPILER_RT "${LLVM_LIBGCC_PATH_TO_RTLIB}" PARENT_SCOPE) + return() + endif() + + execute_process(COMMAND "${CMAKE_CXX_COMPILER}" + ${CMAKE_CXX_FLAGS} + --rtlib=compiler-rt + --print-libgcc-file-name + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE LLVM_LIBGCC_COMPILER_RT) + string(STRIP "${LLVM_LIBGCC_COMPILER_RT}" LLVM_LIBGCC_COMPILER_RT) + + if(HAD_ERROR) + message(STATUS "llvm-libgcc unable to find compiler-rt builtins: got return code ${HAD_ERROR}") + unset(LLVM_LIBGCC_COMPILER_RT) + return() + endif() + + if(NOT EXISTS "${LLVM_LIBGCC_COMPILER_RT}") + message(STATUS "llvm-libgcc unable to find path '${LLVM_LIBGCC_COMPILER_RT}'") + unset(LLVM_LIBGCC_COMPILER_RT) + endif() + + set(LLVM_LIBGCC_COMPILER_RT "${LLVM_LIBGCC_COMPILER_RT}" PARENT_SCOPE) +endfunction() + +set(CompilerRT_FOUND OFF) +if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + building_compiler_rt() +endif() + +if(NOT CompilerRT_FOUND) + find_external_compiler_rt() + if(LLVM_LIBGCC_COMPILER_RT) + string(REGEX REPLACE "^${LLVM_LIBGCC_SYSROOT}/lib${LLVMLIB_DIR_SUFFIX}/*" "" + LLVM_LIBGCC_COMPILER_RT "${LLVM_LIBGCC_COMPILER_RT}") + message(STATUS "llvm-libgcc is using a pre-installed compiler-rt: ${LLVM_LIBGCC_COMPILER_RT}") + set(CompilerRT_FOUND ON) + endif() +endif() + +find_package_handle_standard_args(CompilerRT REQUIRED_VARS CompilerRT_FOUND) diff --git a/llvm/tools/llvm-libgcc/FindLLVMLibunwind.cmake b/llvm/tools/llvm-libgcc/FindLLVMLibunwind.cmake new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/FindLLVMLibunwind.cmake @@ -0,0 +1,56 @@ +include(FindPackageHandleStandardArgs) + +function(building_libunwind) + list(FIND LLVM_ENABLE_PROJECTS libunwind LLVM_LIBGCC_HAS_LIBUNWIND) + if(NOT LLVM_LIBGCC_HAS_LIBUNWIND) + return() + endif() + + if(NOT LIBUNWIND_USE_COMPILER_RT) + message(SEND_ERROR + "When we're building llvm-libgcc alongside libunwind, we need to set " + "'-DLIBUNWIND_USE_COMPILER_RT=On'.") + endif() + + if(LIBUNWIND_INSTALL_SHARED_LIBRARY) + message(SEND_ERROR + "When we're building llvm-libgcc alongside libunwind, llvm-libgcc will " + "be the owner of libunwind.so. To prevent the projects from clashing, we " + "need to set '-DLIBUNWIND_INSTALL_SHARED_LIBRARY=Off'.") + endif() + + if(NOT (LIBUNWIND_SUPPORTS_FNO_EXCEPTIONS_FLAG AND + LIBUNWIND_SUPPORTS_FUNWIND_TABLES_FLAG)) + message(SEND_ERROR + "Compiler doesn't support generation of unwind tables if exception " + "support is disabled. Building libunwind DSO with runtime dependency " + "on C++ ABI library is not supported.") + endif() + + set(LLVM_LIBGCC_UNWIND_STATIC unwind_static PARENT_SCOPE) + set(LLVMLibunwind_FOUND ON PARENT_SCOPE) + message(STATUS "llvm-libgcc is using in-tree libunwind") +endfunction() + +function(find_external_libunwind) + if (NOT EXISTS "${LLVM_LIBGCC_LIBUNWIND_DIR}/libunwind.a") + message(SEND_ERROR + "When using LLVM_LIBGCC_LIBUNWIND_DIR='${LLVM_LIBGCC_LIBUNWIND_DIR}', we " + "couldn't find '${LLVM_LIBGCC_LIBUNWIND_DIR}/libunwind.a'. There could " + "be a few reasons for this (e.g. typo in path or wrong permissions for " + "file), and a manual inspection is necessary.") + endif() + + set(LLVM_LIBGCC_UNWIND_STATIC "${LLVM_LIBGCC_LIBUNWIND_DIR}/libunwind.a" PARENT_SCOPE) + set(LLVMLibunwind_FOUND ON PARENT_SCOPE) +endfunction() + +set(LLVMLibunwind_FOUND OFF) +if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + building_libunwind() +else() + find_external_libunwind() + message(STATUS "llvm-libgcc is using a pre-built libunwind: ${LLVM_LIBGCC_UNWIND_STATIC}") +endif() + +find_package_handle_standard_args(LLVMLibunwind REQUIRED_VARS LLVMLibunwind_FOUND) diff --git a/llvm/tools/llvm-libgcc/docs/LLVMLibgcc.rst b/llvm/tools/llvm-libgcc/docs/LLVMLibgcc.rst new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/docs/LLVMLibgcc.rst @@ -0,0 +1,190 @@ +.. llvm-libgcc: + +=========== +llvm-libgcc +=========== + +.. contents:: + :local: + +**Note that these instructions assume a Linux and bash-friendly environment. +YMMV if you’re on a non Linux-based platform.** + +.. _introduction: + +Motivation +============ + +Enabling libunwind as a replacement for libgcc on Linux has proven to be +challenging since libgcc_s.so is a required dependency in the [Linux standard +base][5]. Some software is transitively dependent on libgcc because glibc makes +hardcoded calls to functions in libgcc_s. For example, the function +``__GI___backtrace`` eventually makes its way to a [hardcoded dlopen to libgcc_s' +_Unwind_Backtrace][1]. Since libgcc_{eh.a,s.so} and libunwind have the same ABI, +but different implementations, the two libraries end up [cross-talking, which +ultimately results in a segfault][2]. + +To solve this problem, libunwind needs libgcc "front" that is, link the +necessary functions from compiler-rt and libunwind into an archive and shared +object that advertise themselves as ``libgcc.a``, ``libgcc_eh.a``, and +``libgcc_s.so``, so that glibc’s baked calls are diverted to the correct objects +in memory. Fortunately for us, compiler-rt and libunwind use the same ABI as the +libgcc family, so the problem is solvable at the llvm-project configuration +level: no program source needs to be edited. Thus, the end result is for a +distro manager to configure their LLVM build with a flag that indicates they +want to archive compiler-rt/unwind as libgcc. We achieve this by compiling +libunwind with all the symbols necessary for compiler-rt to emulate the libgcc +family, and then generate symlinks named for our "libgcc" that point to their +corresponding libunwind counterparts. + +.. _alternatives + +Alternatives +============ + +We alternatively considered patching glibc so that the source doesn't directly +refer to libgcc, but rather _defaults_ to libgcc, so that a system preferring +compiler-rt/libunwind can point to these libraries at the config stage instead. +Even if we modified the Linux standard base, this alternative won't work because +binaries that are built using libgcc will still end up having cross-talk between +the differing implementations. + +.. _target audience: + +Target audience +=============== + +llvm-libgcc is not for the casual LLVM user. It is intended to be used by distro +managers who want to replace libgcc with compiler-rt and libunwind, but cannot +fully abandon the libgcc family (e.g. because they are dependent on glibc). Such +managers must have worked out their compatibility requirements ahead of using +llvm-libgcc. + +.. _cmake options: + +CMake options +============= + +.. option:: `LLVM_LIBGCC_TARGET` + + **Required** + + The target for which llvm-libgcc is being built. This can't be inferred from + ``LLVM_TARGETS_TO_BUILD``, and presently only supports one target at a time. + +.. option:: `LLVM_LIBGCC_SYSROOT` + + **Default value**: ``${CMAKE_INSTALL_PREFIX}`` + + Transforms an absolute path into a relative path starting from the specified + directory. This variable is only used when performing an out-of-tree build. + +.. option:: `LLVM_LIBGCC_COMPILER_RT_INSTALL_DIRECTORY` + + Path to compiler-rt. Overrides building compiler-rt in-tree, and is required + when building out-of-tree when ``CMAKE_CXX_COMPILER`` isn't Clang. + +The following CMake options are not used by llvm-libgcc but are required when +building in-tree. + +.. option:: `COMPILER_RT_BUILD_BUILTINS=On` + +.. option:: `COMPILER_RT_BUILTINS_HIDE_SYMBOLS=Off` + + Necessary for exposing symbols that libgcc_s exposes, but compiler-rt doesn't + by default. This variable should be set when building libunwind out-of-tree + too. + +.. option:: `LIBUNWIND_USE_COMPILER_RT=On` + +.. option:: `LIBUNWIND_INSTALL_SHARED_LIBRARY` + + llvm-libgcc generates both `libunwind.so` and `libgcc_s.so`, so we want to + avoid having libunwind generate this too (otherwise there would be a clash). + This variable should be set when building libunwind out-of-tree too. + +.. _building llvm-libgcc out of tree + +Building llvm-libgcc out of tree +================================ + +Building llvm-libgcc out of tree requires a compiler that supports compiler-rt +when its builtin symbols are exported. This usually means having two build trees +instead of the usual one. + +.. code-block:: bash + + # Assumes $(PWD) is /path/to/llvm-project + $ mkdir -p build + $ cd build + +.. _Building Clang + +Building Clang +-------------- + +The first build tree is a mostly conventional build tree and gets you a Clang +build with these compiler-rt symbols exposed. + +.. code-block:: bash + # Assumes $(PWD) is /path/to/llvm-project + $ cmake -GNinja -S llvm -B build-primary \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/tmp/llvm-libgcc-experiment \ + -DLLVM_ENABLE_PROJECTS='clang;compiler-rt' \ + -DLLVM_ENABLE_RUNTIMES='libcxx;libcxxabi;libunwind' \ + -DCOMPILER_RT_BUILTINS_HIDE_SYMBOLS=Off \ + -DLIBUNWIND_INSTALL_SHARED_LIBRARY=Off \ + -DLIBUNWIND_ENABLE_SHARED=Off \ + -DLIBUNWIND_USE_COMPILER_RT=On \ + -DLIBUNWIND_HAS_COMMENT_LIB_PRAGMA=Off \ + -DLIBUNWIND_HAS_DL_LIB=Off \ + -DLIBUNWIND_HAS_PTHREAD_LIB=Off + $ ninja -C build-primary install + +``LIBUNWIND_HAS_COMMENT_LIB_PRAGMA``, ``LIBUNWIND_HAS_DL_LIB``, and +``LIBUNWIND_HAS_PTHREAD_LIB`` are not strictly necessary, but are useful to +prevent requiring your libunwind dependents to also link with libdl and +libpthread. + +.. _Building llvm-libgcc + +Building llvm-libgcc +------------------ + +Now that we've built the prerequisites, we can build llvm-libgcc in a second +tree. We build llvm-libgcc for x86_64 in this example, but it's possible to +replicate for any architecture that has a `version script`_ in the +``version-scripts`` directory (presently i686, x86_64, armhf, and aarch64). + +.. _version script: https://sourceware.org/binutils/docs/ld/VERSION.html + +.. code-block:: bash + + # Assumes $(PWD) is /path/to/llvm-project + $ export LLVM_LIBGCC_SYSROOT=/tmp/llvm-libgcc-experiment + $ export CC="${LLVM_LIBGCC_SYSROOT}/bin/clang" CXX="${LLVM_LIBGCC_SYSROOT}/bin/clang++" + $ cmake -GNinja -S llvm/tools/llvm-libgcc -B build-libgcc \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="${LLVM_LIBGCC_SYSROOT}" \ + -DLLVM_DEFAULT_TARGET_TRIPLE=x86_64-unknown-linux-gnu \ + -DLLVM_LIBGCC_LIBUNWIND_DIR="${LLVM_LIBGCC_SYSROOT}/lib/x86_64-unknown-linux-gnu" + $ ninja -C build-libgcc install + +``${LLVM_LIBGCC_SYSROOT}/lib/x86_64-unknown-linux-gnu`` is the path to +``libunwind.a``. The target triple is determined by setting the flag +``LLVM_RUNTIME_TARGETS`` in the Clang build: make sure they match. + +## Verifying your results + +This gets you a copy of libunwind with the libgcc symbols. You can verify this +using ``readelf``. + +.. code-block:: bash + + $ llvm-readelf -W --dyn-syms "${LLVM_LIBGCC_SYSROOT}/lib/libunwind.so" | grep FUNC | grep GCC_3.0 + + +Roughly sixty symbols should appear, all suffixed with ``@@GCC_3.0``. You can +replace ``GCC_3.0`` with any of the supported version names in the version +script you’re exporting to verify that the symbols are exported. diff --git a/llvm/tools/llvm-libgcc/lib/CMakeLists.txt b/llvm/tools/llvm-libgcc/lib/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/lib/CMakeLists.txt @@ -0,0 +1,60 @@ +include(CheckLibraryExists) + +add_library(unwind_shared SHARED blank.c) +add_dependencies(unwind_shared always_run_target) +set_target_properties(unwind_shared + PROPERTIES + LINKER_LANGUAGE C + OUTPUT_NAME "unwind" + VERSION "1.0" + SOVERSION "1" + POSITION_INDEPENDENT_CODE ON) +target_link_options( + unwind_shared PRIVATE + -Wl,-nostdlib + -Wl,--whole-archive + -Wl,${LLVM_LIBGCC_SYSROOT}/lib${LLVMLIB_DIR_SUFFIX}/${LLVM_LIBGCC_UNWIND_STATIC} + -Wl,${LLVM_LIBGCC_SYSROOT}/lib${LLVMLIB_DIR_SUFFIX}/${LLVM_LIBGCC_COMPILER_RT} + -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/../gcc_s.ver + -Wl,--no-whole-archive +) +check_library_exists(m sin "" LLVM_LIBGCC_HAS_LIBM) +check_library_exists(c printf "" LLVM_LIBGCC_HAS_LIBC) +target_link_libraries( + unwind_shared PRIVATE + $<$:m> + $<$:c> +) + +add_custom_target(synth_libgcc ALL + DEPENDS "${LLVM_LIBGCC_SYSROOT}/lib${LLVMLIB_DIR_SUFFIX}/${LLVM_LIBGCC_COMPILER_RT}" unwind_shared + COMMAND ${CMAKE_COMMAND} -E create_symlink + "${LLVM_LIBGCC_COMPILER_RT}" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libgcc.a") +add_custom_target(synth_libgcc_eh ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink + "${LLVM_LIBGCC_UNWIND_STATIC}" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libgcc_eh.a") +add_custom_target(synth_libgcc_s ALL + DEPENDS unwind_shared + COMMAND ${CMAKE_COMMAND} -E create_symlink + "libunwind.so" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libgcc_s.so") +add_custom_target(synth_libgcc_s1 ALL + DEPENDS unwind_shared + COMMAND ${CMAKE_COMMAND} -E create_symlink + "libunwind.so.1" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libgcc_s.so.1") + +add_custom_target(unwind + DEPENDS + unwind_shared + synth_libgcc + synth_libgcc_eh + synth_libgcc_s + synth_libgcc_s1) +set(LLVM_LIBGCC_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX} CACHE PATH "") +install(TARGETS unwind_shared + LIBRARY DESTINATION "${LLVM_LIBGCC_INSTALL_LIBRARY_DIR}" COMPONENT unwind + ARCHIVE DESTINATION "${LLVM_LIBGCC_INSTALL_LIBRARY_DIR}" COMPONENT unwind + RUNTIME DESTINATION bin COMPONENT unwind) +install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libgcc.a" TYPE LIB) +install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libgcc_eh.a" TYPE LIB) +install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libgcc_s.so" TYPE LIB) +install(FILES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libgcc_s.so.1" TYPE LIB) diff --git a/llvm/tools/llvm-libgcc/lib/blank.c b/llvm/tools/llvm-libgcc/lib/blank.c new file mode 100644 diff --git a/llvm/tools/llvm-libgcc/version-scripts/32-bit.ver.in b/llvm/tools/llvm-libgcc/version-scripts/32-bit.ver.in new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/32-bit.ver.in @@ -0,0 +1,26 @@ +__ashldi3@GCC_3.0 +__ashrdi3@GCC_3.0 +__cmpdi2@GCC_3.0 +__fixdfdi@GCC_3.0 +__fixsfdi@GCC_3.0 +__fixunsdfsi@GCC_3.0 +__fixunssfsi@GCC_3.0 +__floatdidf@GCC_3.0 +__floatdisf@GCC_3.0 +__lshrdi3@GCC_3.0 +__muldi3@GCC_3.0 +__negdi2@GCC_3.0 +__ucmpdi2@GCC_3.0 +__udivmoddi4@GCC_3.0 +__clzsi2@GCC_3.4 +__ctzsi2@GCC_3.4 +__paritysi2@GCC_3.4 +__popcountsi2@GCC_3.4 +__floatundidf@GCC_4.2.0 +__floatundisf@GCC_4.2.0 +__ffssi2@GCC_4.3.0 +__divmoddi4@GCC_7.0.0 +__divdi3@GLIBC_2.0 +__moddi3@GLIBC_2.0 +__udivdi3@GLIBC_2.0 +__umoddi3@GLIBC_2.0 diff --git a/llvm/tools/llvm-libgcc/version-scripts/64-bit.ver.in b/llvm/tools/llvm-libgcc/version-scripts/64-bit.ver.in new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/64-bit.ver.in @@ -0,0 +1,31 @@ +__ashlti3@GCC_3.0 +__ashrti3@GCC_3.0 +__cmpti2@GCC_3.0 +__divti3@GCC_3.0 +__ffsti2@GCC_3.0 +__fixdfti@GCC_3.0 +__fixsfti@GCC_3.0 +__fixunssfti@GCC_3.0 +__floattidf@GCC_3.0 +__lshrti3@GCC_3.0 +__modti3@GCC_3.0 +__multi3@GCC_3.0 +__negti2@GCC_3.0 +__ucmpti2@GCC_3.0 +__udivmodti4@GCC_3.0 +__udivti3@GCC_3.0 +__umodti3@GCC_3.0 +__fixunsdfti@GCC_3.0 +__floattisf@GCC_3.0 +__clzti2@GCC_3.4 +__ctzti2@GCC_3.4 +__parityti2@GCC_3.4 +__popcountti2@GCC_3.4 +__absvti2@GCC_3.4.4 +__addvti3@GCC_3.4.4 +__mulvti3@GCC_3.4.4 +__negvti2@GCC_3.4.4 +__subvti3@GCC_3.4.4 +__floatuntidf@GCC_4.2.0 +__floatuntisf@GCC_4.2.0 +__divmodti4@GCC_7.0.0 diff --git a/llvm/tools/llvm-libgcc/version-scripts/aarch64.ver.in b/llvm/tools/llvm-libgcc/version-scripts/aarch64.ver.in new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/aarch64.ver.in @@ -0,0 +1,32 @@ +__addtf3@GCC_3.0 +__divtf3@GCC_3.0 +__eqtf2@GCC_3.0 +__extenddftf2@GCC_3.0 +__extendsftf2@GCC_3.0 +__fixtfdi@GCC_3.0 +__fixtfsi@GCC_3.0 +__fixtfti@GCC_3.0 +__fixunstfdi@GCC_3.0 +__fixunstfsi@GCC_3.0 +__fixunstfti@GCC_3.0 +__floatditf@GCC_3.0 +__floatsitf@GCC_3.0 +__floattitf@GCC_3.0 +__getf2@GCC_3.0 +__gttf2@GCC_3.0 +__letf2@GCC_3.0 +__lttf2@GCC_3.0 +__multf3@GCC_3.0 +__netf2@GCC_3.0 +__subtf3@GCC_3.0 +__trunctfdf2@GCC_3.0 +__trunctfsf2@GCC_3.0 +__powitf2@GCC_4.0.0 +__divtc3@GCC_4.0.0 +__multc3@GCC_4.0.0 +__floatunditf@GCC_4.2.0 +__floatunsitf@GCC_4.2.0 +__floatuntitf@GCC_4.2.0 +__unordtf2@GCC_4.5.0 +__deregister_frame@GLIBC_2.0 +__register_frame@GLIBC_2.0 diff --git a/llvm/tools/llvm-libgcc/version-scripts/armhf.ver.in b/llvm/tools/llvm-libgcc/version-scripts/armhf.ver.in new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/armhf.ver.in @@ -0,0 +1,107 @@ +__adddf3@GCC_3.0 +__addsf3@GCC_3.0 +__aeabi_cdcmpeq@GCC_3.5 +__aeabi_cdcmple@GCC_3.5 +__aeabi_cdrcmple@GCC_3.5 +__aeabi_cfcmpeq@GCC_3.5 +__aeabi_cfcmple@GCC_3.5 +__aeabi_cfrcmple@GCC_3.5 +__aeabi_d2f@GCC_3.5 +__aeabi_d2iz@GCC_3.5 +__aeabi_d2lz@GCC_3.5 +__aeabi_d2uiz@GCC_3.5 +__aeabi_d2ulz@GCC_3.5 +__aeabi_dadd@GCC_3.5 +__aeabi_dcmpeq@GCC_3.5 +__aeabi_dcmpge@GCC_3.5 +__aeabi_dcmpgt@GCC_3.5 +__aeabi_dcmple@GCC_3.5 +__aeabi_dcmplt@GCC_3.5 +__aeabi_dcmpun@GCC_3.5 +__aeabi_ddiv@GCC_3.5 +__aeabi_dmul@GCC_3.5 +__aeabi_dneg@GCC_3.5 +__aeabi_drsub@GCC_3.5 +__aeabi_dsub@GCC_3.5 +__aeabi_f2d@GCC_3.5 +__aeabi_f2iz@GCC_3.5 +__aeabi_f2lz@GCC_3.5 +__aeabi_f2uiz@GCC_3.5 +__aeabi_f2ulz@GCC_3.5 +__aeabi_fadd@GCC_3.5 +__aeabi_fcmpeq@GCC_3.5 +__aeabi_fcmpge@GCC_3.5 +__aeabi_fcmpgt@GCC_3.5 +__aeabi_fcmple@GCC_3.5 +__aeabi_fcmplt@GCC_3.5 +__aeabi_fcmpun@GCC_3.5 +__aeabi_fdiv@GCC_3.5 +__aeabi_fmul@GCC_3.5 +__aeabi_fneg@GCC_3.5 +__aeabi_frsub@GCC_3.5 +__aeabi_fsub@GCC_3.5 +__aeabi_i2d@GCC_3.5 +__aeabi_i2f@GCC_3.5 +__aeabi_idiv@GCC_3.5 +__aeabi_idiv0@GCC_3.5 +__aeabi_idivmod@GCC_3.5 +__aeabi_l2d@GCC_3.5 +__aeabi_l2f@GCC_3.5 +__aeabi_lasr@GCC_3.5 +__aeabi_lcmp@GCC_3.5 +__aeabi_ldiv0@GCC_3.5 +__aeabi_ldivmod@GCC_3.5 +__aeabi_llsl@GCC_3.5 +__aeabi_llsr@GCC_3.5 +__aeabi_lmul@GCC_3.5 +__aeabi_ui2d@GCC_3.5 +__aeabi_ui2f@GCC_3.5 +__aeabi_uidiv@GCC_3.5 +__aeabi_uidivmod@GCC_3.5 +__aeabi_ul2d@GCC_3.5 +__aeabi_ul2f@GCC_3.5 +__aeabi_ulcmp@GCC_3.5 +__aeabi_uldivmod@GCC_3.5 +__aeabi_unwind_cpp_pr0@GCC_3.5 +__aeabi_unwind_cpp_pr1@GCC_3.5 +__aeabi_unwind_cpp_pr2@GCC_3.5 +__divdf3@GCC_3.0 +__divsf3@GCC_3.0 +__divsi3@GCC_3.0 +__eqdf2@GCC_3.0 +__eqsf2@GCC_3.0 +__extendsfdf2@GCC_3.0 +__fixdfsi@GCC_3.0 +__fixsfsi@GCC_3.0 +__floatsidf@GCC_3.0 +__floatsisf@GCC_3.0 +__floatunsidf@GCC_4.2.0 +__floatunsisf@GCC_4.2.0 +__gedf2@GCC_3.0 +__gesf2@GCC_3.0 +__gnu_unwind_frame@GCC_3.5 +__gtdf2@GCC_3.0 +__gtsf2@GCC_3.0 +__ledf2@GCC_3.0 +__lesf2@GCC_3.0 +__ltdf2@GCC_3.0 +__ltsf2@GCC_3.0 +__modsi3@GCC_3.0 +__muldf3@GCC_3.0 +__mulsf3@GCC_3.0 +__nedf2@GCC_3.0 +__negdf2@GCC_3.0 +__negsf2@GCC_3.0 +__nesf2@GCC_3.0 +__subdf3@GCC_3.0 +__subsf3@GCC_3.0 +__truncdfsf2@GCC_3.0 +__udivsi3@GCC_3.0 +__umodsi3@GCC_3.0 +__unorddf2@GCC_3.3.4 +__unordsf2@GCC_3.3.4 +_Unwind_Complete@GCC_3.5 +_Unwind_VRS_Get@GCC_3.5 +_Unwind_VRS_Pop@GCC_3.5 +_Unwind_VRS_Set@GCC_3.5 +_Unwind_Backtrace@GCC_4.3.0 diff --git a/llvm/tools/llvm-libgcc/version-scripts/common.ver.in b/llvm/tools/llvm-libgcc/version-scripts/common.ver.in new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/common.ver.in @@ -0,0 +1,39 @@ +__absvdi2@GCC_3.0 +__absvsi2@GCC_3.0 +__addvdi3@GCC_3.0 +__addvsi3@GCC_3.0 +__clear_cache@GCC_3.0 +__ffsdi2@GCC_3.0 +__fixunsdfdi@GCC_3.0 +__fixunssfdi@GCC_3.0 +__mulvdi3@GCC_3.0 +__mulvsi3@GCC_3.0 +__negvdi2@GCC_3.0 +__negvsi2@GCC_3.0 +__subvdi3@GCC_3.0 +__subvsi3@GCC_3.0 +_Unwind_DeleteException@GCC_3.0 +_Unwind_ForcedUnwind@GCC_3.0 +_Unwind_GetDataRelBase@GCC_3.0 +_Unwind_GetLanguageSpecificData@GCC_3.0 +_Unwind_GetRegionStart@GCC_3.0 +_Unwind_GetTextRelBase@GCC_3.0 +_Unwind_RaiseException@GCC_3.0 +_Unwind_Resume@GCC_3.0 +_Unwind_GetCFA@GCC_3.3 +_Unwind_Resume_or_Rethrow@GCC_3.3 +__gcc_personality_v0@GCC_3.3.1 +__clzdi2@GCC_3.4 +__ctzdi2@GCC_3.4 +__paritydi2@GCC_3.4 +__popcountdi2@GCC_3.4 +__enable_execute_stack@GCC_3.4.2 +__divdc3@GCC_4.0.0 +__divsc3@GCC_4.0.0 +__muldc3@GCC_4.0.0 +__mulsc3@GCC_4.0.0 +__powidf2@GCC_4.0.0 +__powisf2@GCC_4.0.0 +__bswapdi2@GCC_4.3.0 +__bswapsi2@GCC_4.3.0 +__emutls_get_address@GCC_4.3.0 diff --git a/llvm/tools/llvm-libgcc/version-scripts/generate_version_script.py b/llvm/tools/llvm-libgcc/version-scripts/generate_version_script.py new file mode 100755 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/generate_version_script.py @@ -0,0 +1,71 @@ +#!/usr/bin/python + +import argparse +from collections import OrderedDict +import os +import sys + + +def read_args(): + parser = argparse.ArgumentParser() + parser.add_argument('--target', type=str, required=True) + target = parser.parse_args().target + target_prefix = target.split('-')[0] if not target.startswith( + 'arm-') and not target.endswith('-gnueabihf') else 'armhf' + choices = ['aarch64', 'armhf', 'i386', 'x86_64'] + if target_prefix not in choices: + print(f'--target must be one of {choices}, but we got {target}', + file=sys.stderr) + sys.exit(1) + return target_prefix + + +def read(template, mappings): + path = f'{os.path.dirname(os.path.realpath(__file__))}/{template}.ver.in' + with open(path, 'r') as f: + for line in f: + line = line.strip() + symbol, version = line.split('@') + if version not in mappings: + mappings[version] = set([]) + mappings[version].add(symbol) + return mappings + + +def generate_mapping(target): + mapping = read('common', {'GCC_3.0': set([])}) + mapping = read(target, mapping) + + if target == 'aarch64' or target == 'x86_64': + mapping = read('64-bit', mapping) + elif target == 'armhf' or target == 'i386': + mapping = read('32-bit', mapping) + + if target == 'i386' or target == 'x86_64': + mapping = read('x86', mapping) + + if target != 'armhf': + mapping = read('non-armhf', mapping) + return mapping + + +def generate_version_script(mapping): + version_script = str() + for (version, symbols) in mapping.items(): + version_script += f'{version} {{\n' + sorted_symbols = sorted(symbols) + for symbol in sorted_symbols: + version_script += f' {symbol};\n' + version_script += '};\n\n' + return version_script + + +def main(): + mapping = OrderedDict(sorted(generate_mapping(read_args()).items())) + version_script = generate_version_script(mapping) + with open('gcc_s.ver', 'w') as f: + f.write(version_script) + + +if __name__ == '__main__': + main() diff --git a/llvm/tools/llvm-libgcc/version-scripts/i386.ver.in b/llvm/tools/llvm-libgcc/version-scripts/i386.ver.in new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/i386.ver.in @@ -0,0 +1,10 @@ +__register_frame_info@GLIBC_2.0 +__register_frame_info_table@GLIBC_2.0 +__register_frame_table@GLIBC_2.0 +__deregister_frame_info@GLIBC_2.0 +__fixunsxfsi@GCC_3.0 +__fixxfdi@GCC_3.0 +__floatdixf@GCC_3.0 +__floatundixf@GCC_4.2.0 +__deregister_frame@GLIBC_2.0 +__register_frame@GLIBC_2.0 diff --git a/llvm/tools/llvm-libgcc/version-scripts/non-armhf.ver.in b/llvm/tools/llvm-libgcc/version-scripts/non-armhf.ver.in new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/non-armhf.ver.in @@ -0,0 +1,8 @@ +_Unwind_Find_FDE@GCC_3.0 +_Unwind_GetGR@GCC_3.0 +_Unwind_GetIP@GCC_3.0 +_Unwind_SetGR@GCC_3.0 +_Unwind_SetIP@GCC_3.0 +_Unwind_Backtrace@GCC_3.3 +_Unwind_FindEnclosingFunction@GCC_3.3 +_Unwind_GetIPInfo@GCC_4.2.0 diff --git a/llvm/tools/llvm-libgcc/version-scripts/x86.ver.in b/llvm/tools/llvm-libgcc/version-scripts/x86.ver.in new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/x86.ver.in @@ -0,0 +1,8 @@ +__deregister_frame_info_bases@GCC_3.0 +__fixunsxfdi@GCC_3.0 +__register_frame_info_bases@GCC_3.0 +__register_frame_info_table_bases@GCC_3.0 +__divxc3@GCC_4.0.0 +__mulxc3@GCC_4.0.0 +__powixf2@GCC_4.0.0 +__cpu_indicator_init@GCC_4.8.0 diff --git a/llvm/tools/llvm-libgcc/version-scripts/x86_64.ver.in b/llvm/tools/llvm-libgcc/version-scripts/x86_64.ver.in new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-libgcc/version-scripts/x86_64.ver.in @@ -0,0 +1,12 @@ +__register_frame_info@GCC_3.0 +__register_frame_info_table@GCC_3.0 +__register_frame_table@GCC_3.0 +__deregister_frame@GCC_3.0 +__deregister_frame_info@GCC_3.0 +__register_frame@GCC_3.0 +__fixunsxfti@GCC_3.0 +__fixxfti@GCC_3.0 +__floattixf@GCC_3.0 +__floatuntixf@GCC_4.2.0 +__divtc3@GCC_4.3.0 +__multc3@GCC_4.3.0