diff --git a/metamod/include/common/stdc++compat.cpp b/metamod/include/common/stdc++compat.cpp new file mode 100644 index 0000000..6177fee --- /dev/null +++ b/metamod/include/common/stdc++compat.cpp @@ -0,0 +1,33 @@ +#include + +#if !defined(_WIN32) +void NORETURN Sys_Error(const char *error, ...); + +// This file adds the necessary compatibility tricks to avoid symbols with +// version GLIBCXX_3.4.16 and bigger, keeping binary compatibility with libstdc++ 4.6.1. +namespace std +{ + // We shouldn't be throwing exceptions at all, but it sadly turns out we call STL (inline) functions that do. + void __throw_out_of_range_fmt(const char *fmt, ...) + { + va_list ap; + char buf[1024]; // That should be big enough. + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + buf[sizeof(buf) - 1] = '\0'; + va_end(ap); + + Sys_Error(buf); + } +}; // namespace std + +// Technically, this symbol is not in GLIBCXX_3.4.20, but in CXXABI_1.3.8, +// but that's equivalent, version-wise. Those calls are added by the compiler +// itself on `new Class[n]` calls. +extern "C" +void __cxa_throw_bad_array_new_length() +{ + Sys_Error("Bad array new length."); +} +#endif // !defined(_WIN32) diff --git a/metamod/src/public_amalgamation.cpp b/metamod/src/public_amalgamation.cpp index d3e05c7..d6efe09 100644 --- a/metamod/src/public_amalgamation.cpp +++ b/metamod/src/public_amalgamation.cpp @@ -1,5 +1,6 @@ #include "precompiled.h" +#include "stdc++compat.cpp" #include "sys_shared.cpp" #include "interface.cpp" #include "crc32c.cpp" diff --git a/metamod/src/utils.cpp b/metamod/src/utils.cpp index c33c671..cc96a90 100644 --- a/metamod/src/utils.cpp +++ b/metamod/src/utils.cpp @@ -305,3 +305,19 @@ bool mem_compare(const char* addr, const char* pattern, size_t len) } return true; } + +void NORETURN Sys_Error(const char *error, ...) +{ + va_list argptr; + static char text[1024]; + + va_start(argptr, error); + vsnprintf(text, sizeof(text), error, argptr); + va_end(argptr); + + META_CONS("FATAL ERROR (shutting down): %s\n", text); + + int *null = 0; + *null = 0; + exit(-1); +} diff --git a/metamod/src/utils.h b/metamod/src/utils.h index 7b733be..92368af 100644 --- a/metamod/src/utils.h +++ b/metamod/src/utils.h @@ -80,5 +80,6 @@ void __declspec(noreturn) do_exit(int exitval); bool is_file_exists_in_gamedir(const char *path); char *full_gamedir_path(const char *path, char *fullpath); bool mem_compare(const char* addr, const char* pattern, size_t len); +void NORETURN Sys_Error(const char *error, ...); extern const char* g_platform_postfixes[4]; diff --git a/shared_icc.gradle b/shared_icc.gradle index ed071b0..d20a9cc 100644 --- a/shared_icc.gradle +++ b/shared_icc.gradle @@ -18,16 +18,17 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind -> extraDefines: [ 'linux': null, '__linux__': null, - 'NDEBUG': null + 'NDEBUG': null, + '_GLIBCXX_USE_CXX11_ABI': 0 ] ), linkerOptions: new GccToolchainConfig.LinkerOptions( interProceduralOptimizations: true, stripSymbolTable: true, - staticLibGcc: true, + staticLibGcc: false, staticIntel: true, - staticLibStdCpp: true, + staticLibStdCpp: false, ), librarianOptions: new GccToolchainConfig.LibrarianOptions( @@ -47,16 +48,17 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind -> extraDefines: [ 'linux': null, '__linux__': null, - 'NDEBUG': null + 'NDEBUG': null, + '_GLIBCXX_USE_CXX11_ABI': 0 ] ), linkerOptions: new GccToolchainConfig.LinkerOptions( interProceduralOptimizations: false, stripSymbolTable: false, - staticLibGcc: true, + staticLibGcc: false, staticIntel: true, - staticLibStdCpp: true, + staticLibStdCpp: false, ), librarianOptions: new GccToolchainConfig.LibrarianOptions(