1.. llvm-libgcc: 2 3=========== 4llvm-libgcc 5=========== 6 7.. contents:: 8 :local: 9 10**Note that these instructions assume a Linux and bash-friendly environment. 11YMMV if you’re on a non Linux-based platform.** 12 13.. _introduction: 14 15Motivation 16============ 17 18Enabling libunwind as a replacement for libgcc on Linux has proven to be 19challenging since libgcc_s.so is a required dependency in the [Linux standard 20base][5]. Some software is transitively dependent on libgcc because glibc makes 21hardcoded calls to functions in libgcc_s. For example, the function 22``__GI___backtrace`` eventually makes its way to a [hardcoded dlopen to libgcc_s' 23_Unwind_Backtrace][1]. Since libgcc_{eh.a,s.so} and libunwind have the same ABI, 24but different implementations, the two libraries end up [cross-talking, which 25ultimately results in a segfault][2]. 26 27To solve this problem, libunwind needs libgcc "front" that is, link the 28necessary functions from compiler-rt and libunwind into an archive and shared 29object that advertise themselves as ``libgcc.a``, ``libgcc_eh.a``, and 30``libgcc_s.so``, so that glibc’s baked calls are diverted to the correct objects 31in memory. Fortunately for us, compiler-rt and libunwind use the same ABI as the 32libgcc family, so the problem is solvable at the llvm-project configuration 33level: no program source needs to be edited. Thus, the end result is for a 34distro manager to configure their LLVM build with a flag that indicates they 35want to archive compiler-rt/unwind as libgcc. We achieve this by compiling 36libunwind with all the symbols necessary for compiler-rt to emulate the libgcc 37family, and then generate symlinks named for our "libgcc" that point to their 38corresponding libunwind counterparts. 39 40.. _alternatives 41 42Alternatives 43============ 44 45We alternatively considered patching glibc so that the source doesn't directly 46refer to libgcc, but rather _defaults_ to libgcc, so that a system preferring 47compiler-rt/libunwind can point to these libraries at the config stage instead. 48Even if we modified the Linux standard base, this alternative won't work because 49binaries that are built using libgcc will still end up having cross-talk between 50the differing implementations. 51 52.. _target audience: 53 54Target audience 55=============== 56 57llvm-libgcc is not for the casual LLVM user. It is intended to be used by distro 58managers who want to replace libgcc with compiler-rt and libunwind, but cannot 59fully abandon the libgcc family (e.g. because they are dependent on glibc). Such 60managers must have worked out their compatibility requirements ahead of using 61llvm-libgcc. 62 63.. _cmake options: 64 65CMake options 66============= 67 68.. option:: `LLVM_LIBGCC_EXPLICIT_OPT_IN` 69 70 **Required** 71 72 Since llvm-libgcc is such a fundamental, low-level component, we have made it 73 difficult to accidentally build, by requiring you to set an opt-in flag. 74 75.. _Building llvm-libgcc 76 77Building llvm-libgcc 78-------------------- 79 80The first build tree is a mostly conventional build tree and gets you a Clang 81build with these compiler-rt symbols exposed. 82 83.. code-block:: bash 84 # Assumes $(PWD) is /path/to/llvm-project 85 $ cmake -GNinja -S llvm -B build-primary \ 86 -DCMAKE_BUILD_TYPE=Release \ 87 -DCMAKE_CROSSCOMPILING=On \ 88 -DCMAKE_INSTALL_PREFIX=/tmp/aarch64-unknown-linux-gnu \ 89 -DLLVM_ENABLE_PROJECTS='clang' \ 90 -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;llvm-libgcc" \ 91 -DLLVM_TARGETS_TO_BUILD=AArch64 \ 92 -DLLVM_DEFAULT_TARGET_TRIPLE=aarch64-unknown-linux-gnu \ 93 -DLLVM_LIBGCC_EXPLICIT_OPT_IN=Yes 94 $ ninja -C build-primary install 95 96It's very important to notice that neither ``compiler-rt``, nor ``libunwind``, 97are listed in ``LLVM_ENABLE_RUNTIMES``. llvm-libgcc makes these subprojects, and 98adding them to this list will cause you problems due to there being duplicate 99targets. As such, configuring the runtimes build will reject explicitly mentioning 100either project with ``llvm-libgcc``. 101 102To avoid issues when building with ``-DLLVM_ENABLE_RUNTIMES=all``, ``llvm-libgcc`` 103is not included, and all runtimes targets must be manually listed. 104 105## Verifying your results 106 107This gets you a copy of libunwind with the libgcc symbols. You can verify this 108using ``readelf``. 109 110.. code-block:: bash 111 112 $ llvm-readelf -W --dyn-syms "${LLVM_LIBGCC_SYSROOT}/lib/libunwind.so" | grep FUNC | grep GCC_3.0 113 114 115Roughly sixty symbols should appear, all suffixed with ``@@GCC_3.0``. You can 116replace ``GCC_3.0`` with any of the supported version names in the version 117script you’re exporting to verify that the symbols are exported. 118 119 120.. _supported platforms: 121 122Supported platforms 123=================== 124 125llvm-libgcc currently supports the following target triples: 126 127* ``aarch64-*-*-*`` 128* ``armv7a-*-*-gnueabihf`` 129* ``i386-*-*-*`` 130* ``x86_64-*-*-*`` 131 132If you would like to support another triple (e.g. ``powerpc64-*-*-*``), you'll 133need to generate a new version script, and then edit ``lib/gcc_s.ver``. 134 135.. _Generating a new version script 136 137Generating a new version script 138------------------------------- 139 140To generate a new version script, we need to generate the list of symbols that 141exist in the set (``clang-builtins.a`` ∪ ``libunwind.a``) ∩ ``libgcc_s.so.1``. 142The prerequisites for generating a version script are a binaries for the three 143aforementioned libraries targeting your architecture (without having built 144llvm-libgcc). 145 146Once these libraries are in place, to generate a new version script, run the 147following command. 148 149.. code-block:: bash 150 151 /path/to/llvm-project 152 $ export ARCH=powerpc64 153 $ llvm/tools/llvm-libgcc/generate_version_script.py \ 154 --compiler_rt=/path/to/libclang_rt.builtins-${ARCH}.a \ 155 --libunwind=/path/to/libunwind.a \ 156 --libgcc_s=/path/to/libgcc_s.so.1 \ 157 --output=${ARCH} 158 159This will generate a new version script a la 160``/path/to/llvm-project/llvm/tools/llvm-libgcc/gcc_s-${ARCH}.ver``, which we use 161in the next section. 162 163.. _Editing ``lib/gcc_s.ver`` 164 165Editing ``lib/gcc_s.ver`` 166------------------------- 167 168Our freshly generated version script is unique to the specific architecture that 169it was generated for, but a lot of the symbols are shared among many platforms. 170As such, we don't check in unique version scripts, but rather have a single 171version script that's run through the C preprocessor to prune symbols we won't 172be using in ``lib/gcc_s.ver``. 173 174Working out which symbols are common is largely a manual process at the moment, 175because some symbols may be shared across different architectures, but not in 176the same versions of libgcc. As such, a symbol appearing in ``lib/gcc_s.ver`` 177doesn't guarantee that the symbol is available for our new architecture: we need 178to verify that the versions are the same, and if they're not, add the symbol to 179the new version section, with the appropriate include guards. 180 181There are a few macros that aim to improve readability. 182 183* ``ARM_GNUEABIHF``, which targets exactly ``arm-*-*-gnueabihf``. 184* ``GLOBAL_X86``, which should be used to target both x86 and x86_64, regardless 185 of the triple. 186* ``GLOBAL_32BIT``, which is be used to target 32-bit platforms. 187* ``GLOBAL_64BIT``, which is be used to target 64-bit platforms. 188