summaryrefslogtreecommitdiff
path: root/llvm-libgcc
diff options
context:
space:
mode:
authorChristopher Di Bella <cjdb@google.com>2021-08-17 20:23:22 +0000
committerChristopher Di Bella <cjdb@google.com>2022-02-16 17:06:45 +0000
commitc5a20b518203613497fa864867fc232648006068 (patch)
tree6151c885938813bd5d5eea4ee49cbb12ef6b1991 /llvm-libgcc
parent0c58e9f4a474c60ed863e6a66c0e1202b4bd6c78 (diff)
downloadllvm-c5a20b518203613497fa864867fc232648006068.tar.gz
[llvm-libgcc] initial commit
Note: the term "libgcc" refers to the all of `libgcc.a`, `libgcc_eh.a`, and `libgcc_s.so`. 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 to build a “libgcc”. 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 user 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. 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 crosstalk between the differing implementations. This problem has been solved in this manner for [FreeBSD][3], and this CL has been tested against [Chrome OS][4]. [1]: https://github.com/bminor/glibc/blob/master/sysdeps/arm/backtrace.c#L68 [2]: https://bugs.chromium.org/p/chromium/issues/detail?id=1162190#c16 [3]: https://github.com/freebsd/freebsd-src/tree/main/lib/libgcc_s [4]: https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/2945947 [5]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/libgcc-s.html Differential Revision: https://reviews.llvm.org/D108416
Diffstat (limited to 'llvm-libgcc')
-rw-r--r--llvm-libgcc/CMakeLists.txt42
-rw-r--r--llvm-libgcc/docs/LLVMLibgcc.rst187
-rwxr-xr-xllvm-libgcc/generate_version_script.py131
-rw-r--r--llvm-libgcc/lib/CMakeLists.txt85
-rw-r--r--llvm-libgcc/lib/blank.c0
-rw-r--r--llvm-libgcc/lib/gcc_s.ver167
6 files changed, 612 insertions, 0 deletions
diff --git a/llvm-libgcc/CMakeLists.txt b/llvm-libgcc/CMakeLists.txt
new file mode 100644
index 000000000000..91c40bbf1cf3
--- /dev/null
+++ b/llvm-libgcc/CMakeLists.txt
@@ -0,0 +1,42 @@
+cmake_minimum_required(VERSION 3.13.4)
+
+if (NOT IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/../libunwind")
+ message(FATAL_ERROR "llvm-libgcc requires being built in a monorepo layout with libunwind available")
+endif()
+
+set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
+
+list(APPEND CMAKE_MODULE_PATH
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
+ "${LLVM_COMMON_CMAKE_UTILS}"
+ "${LLVM_COMMON_CMAKE_UTILS}/Modules"
+ )
+
+project(llvm-libgcc LANGUAGES C CXX ASM)
+
+if(NOT LLVM_LIBGCC_EXPLICIT_OPT_IN)
+ message(FATAL_ERROR
+ "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. If you want to build llvm-libgcc, please add -DLLVM_LIBGCC_EXPLICIT_OPT_IN=Yes "
+ "to your CMake invocation and try again.")
+endif()
+
+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}/bin")
+
+set(COMPILER_RT_BUILD_BUILTINS On)
+set(COMPILER_RT_BUILTINS_HIDE_SYMBOLS Off)
+add_subdirectory("../compiler-rt" "compiler-rt")
+
+set(LIBUNWIND_ENABLE_STATIC On)
+set(LIBUNWIND_ENABLE_SHARED Off)
+set(LIBUNWIND_HAS_COMMENT_LIB_PRAGMA Off)
+set(LIBUNWIND_USE_COMPILER_RT On)
+add_subdirectory("../libunwind" "libunwind")
+
+add_subdirectory(lib)
diff --git a/llvm-libgcc/docs/LLVMLibgcc.rst b/llvm-libgcc/docs/LLVMLibgcc.rst
new file mode 100644
index 000000000000..22dae7afaa6c
--- /dev/null
+++ b/llvm-libgcc/docs/LLVMLibgcc.rst
@@ -0,0 +1,187 @@
+.. 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_EXPLICIT_OPT_IN`
+
+ **Required**
+
+ Since llvm-libgcc is such a fundamental, low-level component, we have made it
+ difficult to accidentally build, by requiring you to set an opt-in flag.
+
+.. _Building llvm-libgcc
+
+Building llvm-libgcc
+--------------------
+
+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_CROSSCOMPILING=On \
+ -DCMAKE_INSTALL_PREFIX=/tmp/aarch64-unknown-linux-gnu \
+ -DLLVM_ENABLE_PROJECTS='clang' \
+ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;llvm-libgcc" \
+ -DLLVM_TARGETS_TO_BUILD=AArch64 \
+ -DLLVM_DEFAULT_TARGET_TRIPLE=aarch64-unknown-linux-gnu \
+ -DLLVM_LIBGCC_EXPLICIT_OPT_IN=Yes
+ $ ninja -C build-primary install
+
+It's very important to notice that neither ``compiler-rt``, nor ``libunwind``,
+are listed in ``LLVM_ENABLE_RUNTIMES``. llvm-libgcc makes these subprojects, and
+adding them to this list will cause you problems due to there being duplicate
+targets. As such, configuring the runtimes build will reject explicitly mentioning
+either project with ``llvm-libgcc``.
+
+To avoid issues when building with ``-DLLVM_ENABLE_RUNTIMES=all``, ``llvm-libgcc``
+is not included, and all runtimes targets must be manually listed.
+
+## 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.
+
+
+.. _supported platforms:
+
+Supported platforms
+===================
+
+llvm-libgcc currently supports the following target triples:
+
+* ``aarch64-*-*-*``
+* ``armv7a-*-*-gnueabihf``
+* ``i386-*-*-*``
+* ``x86_64-*-*-*``
+
+If you would like to support another triple (e.g. ``powerpc64-*-*-*``), you'll
+need to generate a new version script, and then edit ``lib/gcc_s.ver``.
+
+.. _Generating a new version script
+
+Generating a new version script
+-------------------------------
+
+To generate a new version script, we need to generate the list of symbols that
+exist in the set (``clang-builtins.a`` ∪ ``libunwind.a``) ∩ ``libgcc_s.so.1``.
+The prerequisites for generating a version script are a binaries for the three
+aforementioned libraries targeting your architecture (without having built
+llvm-libgcc).
+
+Once these libraries are in place, to generate a new version script, run the
+following command.
+
+.. code-block:: bash
+
+ /path/to/llvm-project
+ $ export ARCH=powerpc64
+ $ llvm/tools/llvm-libgcc/generate_version_script.py \
+ --compiler_rt=/path/to/libclang_rt.builtins-${ARCH}.a \
+ --libunwind=/path/to/libunwind.a \
+ --libgcc_s=/path/to/libgcc_s.so.1 \
+ --output=${ARCH}
+
+This will generate a new version script a la
+``/path/to/llvm-project/llvm/tools/llvm-libgcc/gcc_s-${ARCH}.ver``, which we use
+in the next section.
+
+.. _Editing ``lib/gcc_s.ver``
+
+Editing ``lib/gcc_s.ver``
+-------------------------
+
+Our freshly generated version script is unique to the specific architecture that
+it was generated for, but a lot of the symbols are shared among many platforms.
+As such, we don't check in unique version scripts, but rather have a single
+version script that's run through the C preprocessor to prune symbols we won't
+be using in ``lib/gcc_s.ver``.
+
+Working out which symbols are common is largely a manual process at the moment,
+because some symbols may be shared across different architectures, but not in
+the same versions of libgcc. As such, a symbol appearing in ``lib/gcc_s.ver``
+doesn't guarantee that the symbol is available for our new architecture: we need
+to verify that the versions are the same, and if they're not, add the symbol to
+the new version section, with the appropriate include guards.
+
+There are a few macros that aim to improve readability.
+
+* ``ARM_GNUEABIHF``, which targets exactly ``arm-*-*-gnueabihf``.
+* ``GLOBAL_X86``, which should be used to target both x86 and x86_64, regardless
+ of the triple.
+* ``GLOBAL_32BIT``, which is be used to target 32-bit platforms.
+* ``GLOBAL_64BIT``, which is be used to target 64-bit platforms.
diff --git a/llvm-libgcc/generate_version_script.py b/llvm-libgcc/generate_version_script.py
new file mode 100755
index 000000000000..98850d4f4a2d
--- /dev/null
+++ b/llvm-libgcc/generate_version_script.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python3
+
+# Generates a version script for an architecture so that it can be incorporated
+# into gcc_s.ver.
+
+from collections import defaultdict
+from itertools import chain
+import argparse, subprocess, sys, os
+
+
+def split_suffix(symbol):
+ """
+ Splits a symbol such as `__gttf2@GCC_3.0` into a triple representing its
+ function name (__gttf2), version name (GCC_3.0), and version number (300).
+
+ The version number acts as a priority. Since earlier versions are more
+ accessible and are likely to be used more, the lower the number is, the higher
+ its priortiy. A symbol that has a '@@' instead of '@' has been designated by
+ the linker as the default symbol, and is awarded a priority of -1.
+ """
+ if '@' not in symbol:
+ return None
+ data = [i for i in filter(lambda s: s, symbol.split('@'))]
+ _, version = data[-1].split('_')
+ version = version.replace('.', '')
+ priority = -1 if '@@' in symbol else int(version + '0' *
+ (3 - len(version)))
+ return data[0], data[1], priority
+
+
+def invert_mapping(symbol_map):
+ """Transforms a map from Key->Value to Value->Key."""
+ store = defaultdict(list)
+ for symbol, (version, _) in symbol_map.items():
+ store[version].append(symbol)
+ result = []
+ for k, v in store.items():
+ v.sort()
+ result.append((k, v))
+ result.sort(key=lambda x: x[0])
+ return result
+
+
+def intersection(llvm, gcc):
+ """
+ Finds the intersection between the symbols extracted from compiler-rt.a/libunwind.a
+ and libgcc_s.so.1.
+ """
+ common_symbols = {}
+ for i in gcc:
+ suffix_triple = split_suffix(i)
+ if not suffix_triple:
+ continue
+
+ symbol, version_name, version_number = suffix_triple
+ if symbol in llvm:
+ if symbol not in common_symbols:
+ common_symbols[symbol] = (version_name, version_number)
+ continue
+ if version_number < common_symbols[symbol][1]:
+ common_symbols[symbol] = (version_name, version_number)
+ return invert_mapping(common_symbols)
+
+
+def find_function_names(path):
+ """
+ Runs readelf on a binary and reduces to only defined functions. Equivalent to
+ `llvm-readelf --wide ${path} | grep 'FUNC' | grep -v 'UND' | awk '{print $8}'`.
+ """
+ result = subprocess.run(args=['llvm-readelf', '-su', path],
+ capture_output=True)
+
+ if result.returncode != 0:
+ print(result.stderr.decode('utf-8'), file=sys.stderr)
+ sys.exit(1)
+
+ stdout = result.stdout.decode('utf-8')
+ stdout = filter(lambda x: 'FUNC' in x and 'UND' not in x,
+ stdout.split('\n'))
+ stdout = chain(
+ map(lambda x: filter(None, x), (i.split(' ') for i in stdout)))
+
+ return [list(i)[7] for i in stdout]
+
+
+def to_file(versioned_symbols):
+ path = f'{os.path.dirname(os.path.realpath(__file__))}/new-gcc_s-symbols'
+ with open(path, 'w') as f:
+ f.write('Do not check this version script in: you should instead work '
+ 'out which symbols are missing in `lib/gcc_s.ver` and then '
+ 'integrate them into `lib/gcc_s.ver`. For more information, '
+ 'please see `doc/LLVMLibgcc.rst`.\n')
+ for version, symbols in versioned_symbols:
+ f.write(f'{version} {{\n')
+ for i in symbols:
+ f.write(f' {i};\n')
+ f.write('};\n\n')
+
+
+def read_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--compiler_rt',
+ type=str,
+ help='Path to `libclang_rt.builtins-${ARCH}.a`.',
+ required=True)
+ parser.add_argument('--libunwind',
+ type=str,
+ help='Path to `libunwind.a`.',
+ required=True)
+ parser.add_argument(
+ '--libgcc_s',
+ type=str,
+ help=
+ 'Path to `libgcc_s.so.1`. Note that unlike the other two arguments, this is a dynamic library.',
+ required=True)
+ return parser.parse_args()
+
+
+def main():
+ args = read_args()
+ llvm = find_function_names(args.compiler_rt) + find_function_names(
+ args.libunwind)
+ gcc = find_function_names(args.libgcc_s)
+ versioned_symbols = intersection(llvm, gcc)
+ # TODO(cjdb): work out a way to integrate new symbols in with the existing
+ # ones
+ to_file(versioned_symbols)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/llvm-libgcc/lib/CMakeLists.txt b/llvm-libgcc/lib/CMakeLists.txt
new file mode 100644
index 000000000000..652af46db4cb
--- /dev/null
+++ b/llvm-libgcc/lib/CMakeLists.txt
@@ -0,0 +1,85 @@
+include(CheckLibraryExists)
+include(GNUInstallDirs)
+
+string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+
+add_custom_target(gcc_s_ver ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gcc_s.ver")
+set(LLVM_LIBGCC_GCC_S_VER "${CMAKE_CURRENT_BINARY_DIR}/gcc_s.ver")
+
+add_custom_target(gcc_s.ver ALL
+ DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/gcc_s.ver"
+ COMMAND
+ "${CMAKE_C_COMPILER}"
+ "-E"
+ "-xc" "${CMAKE_CURRENT_SOURCE_DIR}/gcc_s.ver"
+ "-o" "${CMAKE_CURRENT_BINARY_DIR}/gcc_s.ver"
+)
+set_target_properties(gcc_s.ver PROPERTIES
+ OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/gcc_s.ver")
+
+add_library(libgcc_s SHARED blank.c)
+add_dependencies(libgcc_s gcc_s_ver)
+set_target_properties(libgcc_s
+ PROPERTIES
+ LINKER_LANGUAGE C
+ OUTPUT_NAME "unwind"
+ VERSION "1.0"
+ SOVERSION "1"
+ POSITION_INDEPENDENT_CODE ON)
+string(REGEX MATCH "[^-]+" LLVM_LIBGCC_TARGET_ARCH ${CMAKE_C_COMPILER_TARGET})
+target_link_libraries(libgcc_s PRIVATE
+ $<TARGET_OBJECTS:unwind_static>
+ $<TARGET_OBJECTS:clang_rt.builtins-${LLVM_LIBGCC_TARGET_ARCH}>
+)
+target_link_options(libgcc_s PRIVATE
+ -nostdlib
+ -Wl,--version-script,$<TARGET_PROPERTY:gcc_s.ver,OUTPUT_PATH>)
+
+check_library_exists(m sin "" LLVM_LIBGCC_HAS_LIBM)
+target_link_libraries(libgcc_s PRIVATE
+ $<$<BOOL:LLVM_LIBGCC_HAS_LIBM>:m>
+ c
+)
+
+get_filename_component(LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT "${CMAKE_INSTALL_PREFIX}/${LIBUNWIND_INSTALL_LIBRARY_DIR}" ABSOLUTE)
+#string(REPLACE "${CMAKE_INSTALL_FULL_LIBDIR}/" "" LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT "${LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT}")
+
+install(TARGETS libgcc_s
+ LIBRARY DESTINATION "${LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT}" COMPONENT unwind
+ ARCHIVE DESTINATION "${LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT}" COMPONENT unwind
+ RUNTIME DESTINATION bin COMPONENT unwind)
+
+get_compiler_rt_install_dir(${LLVM_LIBGCC_TARGET_ARCH} install_dir_builtins)
+string(REGEX REPLACE "^lib/" "" install_dir_builtins "${install_dir_builtins}")
+string(FIND "${install_dir_builtins}" "clang" install_path_contains_triple)
+if(install_path_contains_triple EQUAL -1)
+ set(builtins_suffix "-${LLVM_LIBGCC_TARGET_ARCH}")
+else()
+ string(PREPEND install_dir_builtins "../")
+endif()
+install(CODE "execute_process(
+ COMMAND \"\${CMAKE_COMMAND}\" -E
+ create_symlink ${install_dir_builtins}/libclang_rt.builtins${builtins_suffix}.a libgcc.a
+ WORKING_DIRECTORY \"\$ENV{DESTDIR}${LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT}\")"
+ COMPONENT unwind)
+
+install(CODE "execute_process(
+ COMMAND \"\${CMAKE_COMMAND}\" -E
+ create_symlink libunwind.a libgcc_eh.a
+ WORKING_DIRECTORY \"\$ENV{DESTDIR}${LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT}\")"
+ COMPONENT unwind)
+install(CODE "execute_process(
+ COMMAND \"\${CMAKE_COMMAND}\" -E
+ create_symlink libunwind.so libgcc_s.so.1.0
+ WORKING_DIRECTORY \"\$ENV{DESTDIR}${LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT}\")"
+ COMPONENT unwind)
+install(CODE "execute_process(
+ COMMAND \"\${CMAKE_COMMAND}\" -E
+ create_symlink libgcc_s.so.1.0 libgcc_s.so.1
+ WORKING_DIRECTORY \"\$ENV{DESTDIR}${LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT}\")"
+ COMPONENT unwind)
+install(CODE "execute_process(
+ COMMAND \"\${CMAKE_COMMAND}\" -E
+ create_symlink libgcc_s.so.1 libgcc_s.so
+ WORKING_DIRECTORY \"\$ENV{DESTDIR}${LLVM_LIBGCC_LIBUNWIND_STATIC_ROOT}\")"
+ COMPONENT unwind)
diff --git a/llvm-libgcc/lib/blank.c b/llvm-libgcc/lib/blank.c
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/llvm-libgcc/lib/blank.c
diff --git a/llvm-libgcc/lib/gcc_s.ver b/llvm-libgcc/lib/gcc_s.ver
new file mode 100644
index 000000000000..d8d038d1f537
--- /dev/null
+++ b/llvm-libgcc/lib/gcc_s.ver
@@ -0,0 +1,167 @@
+// Detect if we're using arm-*-*-gnueabihf
+#if defined(__arm__) && \
+ defined(__ARM_ARCH_7A__) && defined(__ARM_EABI__) && \
+ defined(__ARM_FP) && (__ARM_FP >= 0x04)
+ #define ARM_GNUEABIHF
+#endif
+
+#if !defined(__x86_64__) && \
+ !defined(__aarch64__) && \
+ !defined(__i386__) && \
+ !defined(ARM_GNUEABIHF)
+ #error The only platforms that are currently supported are x86_64, i386, arm-gnueabihf, and aarch64.
+#endif
+
+#if defined(__x86_64__) || defined(__i386__)
+ #define GLOBAL_X86
+#endif
+
+#if __SIZEOF_POINTER__ >= 8
+ #define GLOBAL_64BIT
+#else
+ #define GLOBAL_32BIT
+#endif
+
+GCC_3.0 {
+ __absvdi2; __absvsi2; __addvdi3; __addvsi3; __clear_cache; __ffsdi2;
+ __fixunsdfdi; __fixunssfdi; __mulvdi3; __mulvsi3; __negvdi2; __negvsi2;
+ __subvdi3; __subvsi3;
+ _Unwind_DeleteException;
+ _Unwind_ForcedUnwind;
+ _Unwind_GetDataRelBase;
+ _Unwind_GetLanguageSpecificData;
+ _Unwind_GetRegionStart;
+ _Unwind_GetTextRelBase;
+ _Unwind_RaiseException;
+ _Unwind_Resume;
+};
+
+GCC_3.3 { _Unwind_GetCFA; _Unwind_Resume_or_Rethrow; };
+GCC_3.3.1 { __gcc_personality_v0; };
+GCC_3.4 { __clzdi2; __ctzdi2; __paritydi2; __popcountdi2; };
+GCC_3.4.2 { __enable_execute_stack; };
+GCC_4.0.0 { __divdc3; __divsc3; __muldc3; __mulsc3; __powidf2; __powisf2; };
+GCC_4.3.0 { __bswapdi2; __bswapsi2; __emutls_get_address; };
+
+#if defined(GLOBAL_32BIT)
+ GCC_3.0 {
+ __ashldi3; __ashrdi3; __cmpdi2; __fixdfdi; __fixsfdi; __fixunsdfsi;
+ __fixunssfsi; __floatdidf; __floatdisf; __lshrdi3; __muldi3; __negdi2;
+ __ucmpdi2; __udivmoddi4;
+ };
+
+ GCC_3.4 { __clzsi2; __ctzsi2; __paritysi2; __popcountsi2; };
+ GCC_4.2.0 { __floatundidf; __floatundisf; };
+ GCC_4.3.0 { __ffssi2; };
+ GCC_7.0.0 { __divmoddi4; };
+ GLIBC_2.0 { __divdi3; __moddi3; __udivdi3; __umoddi3; };
+#elif defined(GLOBAL_64BIT)
+ GCC_3.0 {
+ __ashlti3; __ashrti3; __cmpti2; __divti3; __ffsti2; __fixdfti;
+ __fixsfti; __fixunssfti; __floattidf; __lshrti3; __modti3; __multi3;
+ __negti2; __ucmpti2; __udivmodti4; __udivti3; __umodti3; __fixunsdfti;
+ __floattisf;
+ };
+
+ GCC_3.4 { __clzti2; __ctzti2; __parityti2; __popcountti2; };
+ GCC_3.4.4 { __absvti2; __addvti3; __mulvti3; __negvti2; __subvti3; };
+ GCC_4.2.0 { __floatuntidf; __floatuntisf; };
+ GCC_7.0.0 { __divmodti4; };
+#endif
+
+#if defined(GLOBAL_X86)
+ GCC_3.0 {
+ __deregister_frame_info_bases; __fixunsxfdi; __register_frame_info_bases;
+ __register_frame_info_table_bases;
+ };
+
+ GCC_4.0.0 { __divxc3; __mulxc3; __powixf2; };
+ GCC_4.8.0 { __cpu_indicator_init; };
+#endif
+
+#if !defined(ARM_GNUEABIHF)
+ GCC_3.0 {
+ _Unwind_Find_FDE; _Unwind_GetGR; _Unwind_GetIP; _Unwind_SetGR; _Unwind_SetIP;
+ };
+
+ GCC_3.3 { _Unwind_Backtrace; _Unwind_FindEnclosingFunction; };
+ GCC_4.2.0 { _Unwind_GetIPInfo; };
+#else // defined(ARM_GNUEABIHF)
+ GCC_3.0 {
+ __adddf3; __addsf3; __divdf3; __divsf3; __divsi3; __eqdf2;
+ __eqsf2; __extendsfdf2; __fixdfsi; __fixsfsi; __floatsidf; __floatsisf;
+ __gedf2; __gesf2; __gtdf2; __gtsf2; __ledf2; __lesf2;
+ __ltdf2; __ltsf2; __modsi3; __muldf3; __mulsf3; __nedf2;
+ __negdf2; __negsf2; __nesf2; __subdf3; __subsf3; __truncdfsf2;
+ __udivsi3; __umodsi3;
+ };
+
+ GCC_3.3.4 { __unorddf2; __unordsf2; };
+
+ GCC_3.5 {
+ __aeabi_cdcmpeq; __aeabi_cdcmple; __aeabi_cdrcmple; __aeabi_cfcmpeq;
+ __aeabi_cfcmple; __aeabi_cfrcmple; __aeabi_d2f; __aeabi_d2iz;
+ __aeabi_d2lz; __aeabi_d2uiz; __aeabi_d2ulz; __aeabi_dadd;
+ __aeabi_dcmpeq; __aeabi_dcmpge; __aeabi_dcmpgt; __aeabi_dcmple;
+ __aeabi_dcmplt; __aeabi_dcmpun; __aeabi_ddiv; __aeabi_dmul;
+ __aeabi_dneg; __aeabi_drsub; __aeabi_dsub; __aeabi_f2d;
+ __aeabi_f2iz; __aeabi_f2lz; __aeabi_f2uiz; __aeabi_f2ulz;
+ __aeabi_fadd; __aeabi_fcmpeq; __aeabi_fcmpge; __aeabi_fcmpgt;
+ __aeabi_fcmple; __aeabi_fcmplt; __aeabi_fcmpun; __aeabi_fdiv;
+ __aeabi_fmul; __aeabi_fneg; __aeabi_frsub; __aeabi_fsub;
+ __aeabi_i2d; __aeabi_i2f; __aeabi_idiv; __aeabi_idiv0;
+ __aeabi_idivmod; __aeabi_l2d; __aeabi_l2f; __aeabi_lasr;
+ __aeabi_lcmp; __aeabi_ldiv0; __aeabi_ldivmod; __aeabi_llsl;
+ __aeabi_llsr; __aeabi_lmul; __aeabi_ui2d; __aeabi_ui2f;
+ __aeabi_uidiv; __aeabi_uidivmod; __aeabi_ul2d; __aeabi_ul2f;
+ __aeabi_ulcmp; __aeabi_uldivmod; __aeabi_unwind_cpp_pr0;
+ __aeabi_unwind_cpp_pr1; __aeabi_unwind_cpp_pr2;
+ __gnu_unwind_frame;
+ _Unwind_Complete;
+ _Unwind_VRS_Get;
+ _Unwind_VRS_Pop;
+ _Unwind_VRS_Set;
+ };
+
+ GCC_4.2.0 { __floatunsidf; __floatunsisf; };
+ GCC_4.3.0 { _Unwind_Backtrace; };
+#endif
+
+#if defined(__aarch64__)
+ GCC_3.0 {
+ __addtf3; __divtf3; __eqtf2; __extenddftf2; __extendsftf2;
+ __fixtfdi; __fixtfsi; __fixtfti; __fixunstfdi; __fixunstfsi;
+ __fixunstfti; __floatditf; __floatsitf; __floattitf; __getf2;
+ __gttf2; __letf2; __lttf2; __multf3; __netf2;
+ __subtf3; __trunctfdf2; __trunctfsf2;
+ };
+
+ GCC_4.0.0 { __powitf2; __divtc3; __multc3; };
+ GCC_4.2.0 { __floatunditf; __floatunsitf; __floatuntitf; };
+ GCC_4.5.0 { __unordtf2; };
+#endif
+
+#if defined(__aarch64__) || defined(__i386__)
+ GLIBC_2.0 { __deregister_frame; __register_frame; };
+#endif
+
+#if defined(__i386__)
+ GCC_3.0 { __fixunsxfsi; __fixxfdi; __floatdixf; };
+ GCC_4.2.0 { __floatundixf; };
+
+ GLIBC_2.0 {
+ __register_frame_info; __register_frame_info_table; __register_frame_table;
+ __deregister_frame_info;
+ };
+#endif
+
+#if defined(__x86_64__)
+ GCC_3.0 {
+ __register_frame_info; __register_frame_info_table; __register_frame_table;
+ __deregister_frame; __deregister_frame_info; __register_frame;
+ __fixunsxfti; __fixxfti; __floattixf;
+ };
+
+ GCC_4.2.0 { __floatuntixf; };
+ GCC_4.3.0 { __divtc3; __multc3; };
+#endif