зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1643258 - Avoid the use of the __cxa_thread_atexit_impl symbol. r=froydnj
When linking a weak symbol in an object against a library where the symbol is provided with a version, the final binary get a weak versioned symbol reference. It turns out weak versioned symbols still make the dynamic linker need the symbol version, even if all symbols needed with that version are weak. Practically speaking, that means with bug 1634204, we now end up with a weak versioned symbol reference to __cxa_thread_atexit_impl with version GLIBC_2.18, and glibcs without the symbol can't fulfil that version, even though the weak symbol is the only thing we need from that version. This means the check_binary changes in bug 1634204 are too relaxed, so we revert them (although we keep the easier to read conditions in check_dep_versions). We also introduce a hack in stdc++compat.cpp (although it's not technically entirely about libstdc++ compat) so that we avoid the weak symbol reference while keeping the intended baseline for libstdc++ and glibc. Differential Revision: https://phabricator.services.mozilla.com/D79773
This commit is contained in:
Родитель
09750d5dab
Коммит
9d26424253
|
@ -8,6 +8,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <mozilla/Assertions.h>
|
||||
#include <cxxabi.h>
|
||||
|
||||
/* GLIBCXX_3.4.16 is from gcc 4.6.1 (172240)
|
||||
GLIBCXX_3.4.17 is from gcc 4.7.0 (174383)
|
||||
|
@ -144,6 +145,12 @@ namespace std {
|
|||
* depending on optimization level */
|
||||
template basic_ios<char, char_traits<char>>::operator bool() const;
|
||||
} // namespace std
|
||||
|
||||
/* operator delete with size is only available in CXXAPI_1.3.9, equivalent to
|
||||
* GLIBCXX_3.4.21. */
|
||||
void operator delete(void* ptr, size_t size) noexcept(true) {
|
||||
::operator delete(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MOZ_LIBSTDCXX_VERSION >= GLIBCXX_VERSION(3, 4, 23)
|
||||
|
@ -154,3 +161,18 @@ template basic_string<char, char_traits<char>, allocator<char>>::basic_string(
|
|||
const basic_string&, size_t, const allocator<char>&);
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
/* The __cxa_thread_atexit_impl symbol is only available on GLIBC 2.18, but we
|
||||
* want things to keep working on 2.17. It's not actually used directly from
|
||||
* C++ code, but through __cxa_thead_atexit in libstdc++. The problem we have,
|
||||
* though, is that rust's libstd also uses it, introducing a dependency we
|
||||
* don't actually want. Fortunately, we can fall back to libstdc++'s wrapper
|
||||
* (which, on systems without __cxa_thread_atexit_impl, has its own compatible
|
||||
* implementation).
|
||||
* The __cxa_thread_atexit symbol itself is marked CXXABI_1.3.7, which is
|
||||
* equivalent to GLIBCXX_3.4.18.
|
||||
*/
|
||||
extern "C" int __cxa_thread_atexit_impl(void (*dtor)(void*), void* obj,
|
||||
void* dso_handle) {
|
||||
return __cxxabiv1::__cxa_thread_atexit(dtor, obj, dso_handle);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ from mozpack.executables import (
|
|||
|
||||
|
||||
STDCXX_MAX_VERSION = Version('3.4.19')
|
||||
CXXABI_MAX_VERSION = Version('1.3.7')
|
||||
GLIBC_MAX_VERSION = Version('2.17')
|
||||
LIBGCC_MAX_VERSION = Version('4.8')
|
||||
|
||||
|
@ -96,11 +97,8 @@ def iter_symbols(binary):
|
|||
continue
|
||||
addr = int(m.group(0), 16)
|
||||
# The second "column" is 7 one-character items that can be
|
||||
# whitespaces.
|
||||
flags = line[m.end():][:7]
|
||||
# We're only interested whether the symbol might be weak.
|
||||
weak = 'w' in flags
|
||||
|
||||
# whitespaces. We don't have use for their value, so just skip
|
||||
# those.
|
||||
rest = line[m.end() + 9:].split()
|
||||
# The number of remaining colums will vary between ELF and MACHO.
|
||||
# On ELF, we have:
|
||||
|
@ -119,7 +117,6 @@ def iter_symbols(binary):
|
|||
'size': int(rest[1], 16) if ty == ELF else 0,
|
||||
'name': name,
|
||||
'version': ver or None,
|
||||
'weak': weak,
|
||||
}
|
||||
else:
|
||||
export_table = False
|
||||
|
@ -147,7 +144,6 @@ def iter_symbols(binary):
|
|||
'size': 0,
|
||||
'name': name,
|
||||
'version': None,
|
||||
'weak': None,
|
||||
}
|
||||
|
||||
|
||||
|
@ -169,11 +165,6 @@ def check_dep_versions(target, binary, lib, prefix, max_version):
|
|||
if sym['addr'] != 0:
|
||||
continue
|
||||
|
||||
# Versions for weak symbols don't matter, since the code must
|
||||
# handle the case where they're not defined.
|
||||
if sym['weak']:
|
||||
continue
|
||||
|
||||
# No version to check
|
||||
if not sym['version']:
|
||||
continue
|
||||
|
@ -195,6 +186,8 @@ def check_dep_versions(target, binary, lib, prefix, max_version):
|
|||
def check_stdcxx(target, binary):
|
||||
check_dep_versions(
|
||||
target, binary, 'libstdc++', 'GLIBCXX', STDCXX_MAX_VERSION)
|
||||
check_dep_versions(
|
||||
target, binary, 'libstdc++', 'CXXABI', CXXABI_MAX_VERSION)
|
||||
|
||||
|
||||
def check_libgcc(target, binary):
|
||||
|
|
Загрузка…
Ссылка в новой задаче