Strip only the leading underscore from Mach-O symbols

LLVM prepends an underscore to all Mach-O (Apple) symbols. Previously
we stripped all leading underscores, including ones part of the
function's actual name.

This change will make it possible to support AddressSanitizer
instrumentation, which calls functions such as __asan_report_load_n
which need to be resolved from the dynamically linked runtime.

Bug: b/240465596
Change-Id: If1674f4a44ba36f3571d05bcb9ba518962686351
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/67188
Reviewed-by: Alexis Hétu <sugoi@google.com>
Commit-Queue: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Reactor/LLVMJIT.cpp b/src/Reactor/LLVMJIT.cpp
index fb8c27b..d21cf22 100644
--- a/src/Reactor/LLVMJIT.cpp
+++ b/src/Reactor/LLVMJIT.cpp
@@ -545,17 +545,17 @@
 			functions.try_emplace("memset", reinterpret_cast<void *>(memset));
 
 #ifdef __APPLE__
-			functions.try_emplace("sincosf_stret", reinterpret_cast<void *>(__sincosf_stret));
+			functions.try_emplace("__sincosf_stret", reinterpret_cast<void *>(__sincosf_stret));
 #elif defined(__linux__)
 			functions.try_emplace("sincosf", reinterpret_cast<void *>(sincosf));
 #elif defined(_WIN64)
-			functions.try_emplace("chkstk", reinterpret_cast<void *>(__chkstk));
+			functions.try_emplace("__chkstk", reinterpret_cast<void *>(__chkstk));
 #elif defined(_WIN32)
-			functions.try_emplace("chkstk", reinterpret_cast<void *>(_chkstk));
+			functions.try_emplace("_chkstk", reinterpret_cast<void *>(_chkstk));
 #endif
 
 #ifdef __ARM_EABI__
-			functions.try_emplace("aeabi_idivmod", reinterpret_cast<void *>(__aeabi_idivmod));
+			functions.try_emplace("__aeabi_idivmod", reinterpret_cast<void *>(__aeabi_idivmod));
 #endif
 #ifdef __ANDROID__
 			functions.try_emplace("aeabi_unwind_cpp_pr0", reinterpret_cast<void *>(neverCalled));
@@ -580,19 +580,19 @@
 #	endif
 #endif
 #if __has_feature(memory_sanitizer)
-			functions.try_emplace("emutls_get_address", reinterpret_cast<void *>(rr::getTLSAddress));
-			functions.try_emplace("emutls_v.__msan_param_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::param)));
-			functions.try_emplace("emutls_v.__msan_param_origin_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::param_origin)));
-			functions.try_emplace("emutls_v.__msan_retval_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::retval)));
-			functions.try_emplace("emutls_v.__msan_retval_origin_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::retval_origin)));
-			functions.try_emplace("emutls_v.__msan_va_arg_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::va_arg)));
-			functions.try_emplace("emutls_v.__msan_va_arg_origin_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::va_arg_origin)));
-			functions.try_emplace("emutls_v.__msan_va_arg_overflow_size_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::va_arg_overflow_size)));
-			functions.try_emplace("emutls_v.__msan_origin_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::origin)));
+			functions.try_emplace("__emutls_get_address", reinterpret_cast<void *>(rr::getTLSAddress));
+			functions.try_emplace("__emutls_v.__msan_param_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::param)));
+			functions.try_emplace("__emutls_v.__msan_param_origin_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::param_origin)));
+			functions.try_emplace("__emutls_v.__msan_retval_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::retval)));
+			functions.try_emplace("__emutls_v.__msan_retval_origin_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::retval_origin)));
+			functions.try_emplace("__emutls_v.__msan_va_arg_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::va_arg)));
+			functions.try_emplace("__emutls_v.__msan_va_arg_origin_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::va_arg_origin)));
+			functions.try_emplace("__emutls_v.__msan_va_arg_overflow_size_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::va_arg_overflow_size)));
+			functions.try_emplace("__emutls_v.__msan_origin_tls", reinterpret_cast<void *>(static_cast<uintptr_t>(rr::MSanTLS::origin)));
 
 			// TODO(b/155148722): Remove when we no longer unpoison any writes.
-			functions.try_emplace("msan_unpoison", reinterpret_cast<void *>(__msan_unpoison));
-			functions.try_emplace("msan_unpoison_param", reinterpret_cast<void *>(__msan_unpoison_param));
+			functions.try_emplace("__msan_unpoison", reinterpret_cast<void *>(__msan_unpoison));
+			functions.try_emplace("__msan_unpoison_param", reinterpret_cast<void *>(__msan_unpoison_param));
 #endif
 		}
 	};
@@ -618,11 +618,15 @@
 		{
 			auto name = symbol.first;
 
-			// Trim off any underscores from the start of the symbol. LLVM likes
-			// to append these on macOS.
-			auto trimmed = (*name).drop_while([](char c) { return c == '_'; });
+#if defined(__APPLE__)
+			// Trim the underscore from the start of the symbol. LLVM adds it for Mach-O mangling convention.
+			ASSERT((*name)[0] == '_');
+			auto unmangled = (*name).drop_front(1);
+#else
+			auto unmangled = *name;
+#endif
 
-			auto it = resolver.functions.find(trimmed.str());
+			auto it = resolver.functions.find(unmangled.str());
 			if(it != resolver.functions.end())
 			{
 				symbols[name] = llvm::JITEvaluatedSymbol(
@@ -639,7 +643,7 @@
 			// visible (e.g. due to static linking), we may wish to provide an alternate
 			// implementation, and/or it would be a security vulnerability.
 
-			void *address = dlsym(RTLD_DEFAULT, (*symbol.first).data());
+			void *address = dlsym(RTLD_DEFAULT, unmangled.data());
 
 			if(address)
 			{
@@ -652,7 +656,7 @@
 #endif
 
 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
-			missing += (missing.empty() ? "'" : ", '") + (*name).str() + "'";
+			missing += (missing.empty() ? "'" : ", '") + unmangled.str() + "'";
 #endif
 		}