tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

stdc++compat.cpp (7614B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include <ostream>
      6 #include <istream>
      7 #include <sstream>
      8 #include <memory>
      9 #include <string>
     10 #include <stdarg.h>
     11 #include <stdio.h>
     12 #include <mozilla/Assertions.h>
     13 #include <cxxabi.h>
     14 
     15 /*
     16   GLIBCXX_3.4.19 is from gcc 4.8.1 (199309)
     17   GLIBCXX_3.4.20 is from gcc 4.9.0 (199307)
     18   GLIBCXX_3.4.21 is from gcc 5.0 (210290)
     19   GLIBCXX_3.4.22 is from gcc 6.0 (222482)
     20   GLIBCXX_3.4.23 is from gcc 7
     21   GLIBCXX_3.4.24 is from gcc 8
     22   GLIBCXX_3.4.25 is from gcc 8
     23   GLIBCXX_3.4.26 is from gcc 9
     24   GLIBCXX_3.4.27 is from gcc 10
     25   GLIBCXX_3.4.28 is from gcc 10
     26   GLIBCXX_3.4.29 is from gcc 11
     27 
     28 This file adds the necessary compatibility tricks to avoid symbols with
     29 version GLIBCXX_3.4.20 and bigger, keeping binary compatibility with
     30 libstdc++ 4.8.1.
     31 
     32 WARNING: all symbols from this file must be defined weak when they
     33 overlap with libstdc++.
     34 */
     35 
     36 /* Expose the definitions for the old ABI, allowing us to call its functions */
     37 #define _GLIBCXX_THREAD_ABI_COMPAT 1
     38 #include <thread>
     39 
     40 #if !defined(__aarch64__)
     41 /* The __cxa_thread_atexit_impl symbol is only available on GLIBC 2.18, but we
     42 * want things to keep working on 2.17. It's not actually used directly from
     43 * C++ code, but through __cxa_thead_atexit in libstdc++. The problem we have,
     44 * though, is that rust's libstd also uses it, introducing a dependency we
     45 * don't actually want. Fortunately, we can fall back to libstdc++'s wrapper
     46 * (which, on systems without __cxa_thread_atexit_impl, has its own compatible
     47 * implementation).
     48 * The __cxa_thread_atexit symbol itself is marked CXXABI_1.3.7, which is
     49 * equivalent to GLIBCXX_3.4.18.
     50 */
     51 extern "C" int __cxa_thread_atexit_impl(void (*dtor)(void*), void* obj,
     52                                        void* dso_handle) {
     53  return __cxxabiv1::__cxa_thread_atexit(dtor, obj, dso_handle);
     54 }
     55 
     56 namespace std {
     57 
     58 /* We shouldn't be throwing exceptions at all, but it sadly turns out
     59   we call STL (inline) functions that do. This avoids the GLIBCXX_3.4.20
     60   symbol version. */
     61 void __attribute__((weak)) __throw_out_of_range_fmt(char const* fmt, ...) {
     62  va_list ap;
     63  char buf[1024];  // That should be big enough.
     64 
     65  va_start(ap, fmt);
     66  vsnprintf(buf, sizeof(buf), fmt, ap);
     67  buf[sizeof(buf) - 1] = 0;
     68  va_end(ap);
     69 
     70  __throw_range_error(buf);
     71 }
     72 
     73 }  // namespace std
     74 
     75 namespace __cxxabiv1 {
     76 /* Calls to this function are added by the compiler itself on `new Class[n]`
     77 * calls. This avoids the GLIBCXX_3.4.20 symbol version. */
     78 extern "C" void __attribute__((weak)) __cxa_throw_bad_array_new_length() {
     79  MOZ_CRASH();
     80 }
     81 }  // namespace __cxxabiv1
     82 
     83 namespace std {
     84 /* Instantiate this template to avoid GLIBCXX_3.4.21 symbol versions
     85 * depending on optimization level */
     86 template basic_ios<char, char_traits<char>>::operator bool() const;
     87 }  // namespace std
     88 
     89 #  if !defined(MOZ_ASAN) && !defined(MOZ_TSAN)
     90 /* operator delete with size is only available in CXXAPI_1.3.9, equivalent to
     91 * GLIBCXX_3.4.21. */
     92 void operator delete(void* ptr, size_t size) noexcept(true) {
     93  ::operator delete(ptr);
     94 }
     95 #  endif
     96 
     97 /* While we generally don't build with exceptions, we have some host tools
     98 * that do use them. libstdc++ from GCC 5.0 added exception constructors with
     99 * char const* argument. Older versions only have a constructor with
    100 * std::string. This avoids the GLIBCXX_3.4.21 symbol version. */
    101 namespace std {
    102 __attribute__((weak)) runtime_error::runtime_error(char const* s)
    103    : runtime_error(std::string(s)) {}
    104 __attribute__((weak)) out_of_range::out_of_range(char const* s)
    105    : out_of_range(std::string(s)) {}
    106 __attribute__((weak)) invalid_argument::invalid_argument(char const* s)
    107    : invalid_argument(std::string(s)) {}
    108 }  // namespace std
    109 
    110 namespace std {
    111 /* The old ABI has a thread::_M_start_thread(shared_ptr<_Impl_base>),
    112 * while the new has thread::_M_start_thread(unique_ptr<_State>, void(*)()).
    113 * There is an intermediate ABI at version 3.4.21, with
    114 * thread::_M_start_thread(shared_ptr<_Impl_base>, void(*)()).
    115 * The void(*)() parameter is only there to keep a reference to pthread_create
    116 * on the caller side, and is unused in the implementation
    117 * We're creating an entry point for the new and intermediate ABIs, and make
    118 * them call the old ABI. This avoids the GLIBCXX_3.4.21 symbol version. */
    119 __attribute__((weak)) void thread::_M_start_thread(shared_ptr<_Impl_base> impl,
    120                                                   void (*)()) {
    121  _M_start_thread(std::move(impl));
    122 }
    123 }  // namespace std
    124 
    125 #endif  // !defined(__aarch64__)
    126 
    127 namespace std {
    128 /* We need a _Impl_base-derived class wrapping a _State to call the old ABI
    129 * from what we got by diverting the new API. This avoids the GLIBCXX_3.4.22
    130 * symbol version. */
    131 struct StateWrapper : public thread::_Impl_base {
    132  unique_ptr<thread::_State> mState;
    133 
    134  StateWrapper(unique_ptr<thread::_State> aState) : mState(std::move(aState)) {}
    135 
    136  void _M_run() override { mState->_M_run(); }
    137 };
    138 
    139 /* This avoids the GLIBCXX_3.4.22 symbol version. */
    140 __attribute__((weak)) void thread::_M_start_thread(unique_ptr<_State> aState,
    141                                                   void (*)()) {
    142  auto impl = std::make_shared<StateWrapper>(std::move(aState));
    143  _M_start_thread(std::move(impl));
    144 }
    145 
    146 /* For some reason this is a symbol exported by new versions of libstdc++,
    147 * even though the destructor is default there too. This avoids the
    148 * GLIBCXX_3.4.22 symbol version. */
    149 __attribute__((weak)) thread::_State::~_State() = default;
    150 
    151 #if _GLIBCXX_RELEASE >= 9
    152 // Ideally we'd define
    153 //    bool _Sp_make_shared_tag::_S_eq(const type_info& ti) noexcept
    154 // but we wouldn't be able to change its visibility because of the existing
    155 // definition in C++ headers. We do need to change its visibility because we
    156 // don't want it to be shadowing the one provided by libstdc++ itself, because
    157 // it doesn't support RTTI. Not supporting RTTI doesn't matter for Firefox
    158 // itself because it's built with RTTI disabled.
    159 // So we define via the mangled symbol.
    160 // This avoids the GLIBCXX_3.4.26 symbol version.
    161 extern "C" __attribute__((visibility("hidden"))) bool
    162 _ZNSt19_Sp_make_shared_tag5_S_eqERKSt9type_info(const type_info*) noexcept {
    163  return false;
    164 }
    165 #endif
    166 
    167 /* Instantiate this template to avoid GLIBCXX_3.4.23 symbol versions
    168 * depending on optimization level */
    169 template basic_string<char, char_traits<char>, allocator<char>>::basic_string(
    170    const basic_string&, size_t, const allocator<char>&);
    171 
    172 #if _GLIBCXX_RELEASE >= 9
    173 // This avoids the GLIBCXX_3.4.26 symbol version.
    174 template basic_stringstream<char, char_traits<char>,
    175                            allocator<char>>::basic_stringstream();
    176 
    177 template basic_istringstream<char, char_traits<char>,
    178                             allocator<char>>::basic_istringstream();
    179 
    180 template basic_ostringstream<char, char_traits<char>,
    181                             allocator<char>>::basic_ostringstream();
    182 
    183 template char*
    184 basic_string<char, char_traits<char>, allocator<char>>::data() noexcept;
    185 
    186 template basic_stringbuf<char, char_traits<char>,
    187                         allocator<char>>::basic_stringbuf();
    188 
    189 #endif
    190 
    191 #if _GLIBCXX_RELEASE >= 11
    192 // This avoids the GLIBCXX_3.4.29 symbol version.
    193 template void basic_string<char, char_traits<char>, allocator<char>>::reserve();
    194 
    195 template void
    196 basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>::reserve();
    197 
    198 void __attribute__((weak)) __throw_bad_array_new_length() { MOZ_CRASH(); }
    199 #endif
    200 
    201 }  // namespace std