5252#include < cstring>
5353#include < cerrno>
5454
55+ #ifdef _WIN32
56+ // We'll probably want dbghelp.h here
57+ #else
58+ #include < cxxabi.h>
59+ #endif
60+
5561#define DEBUG_BACKTRACING_SETTINGS 0
5662
5763#ifndef lengthof
@@ -773,6 +779,54 @@ _swift_backtraceSetupEnvironment()
773779 *penv = 0 ;
774780}
775781
782+ #ifdef __linux__
783+ struct spawn_info {
784+ const char *path;
785+ char * const *argv;
786+ char * const *envp;
787+ int memserver;
788+ };
789+
790+ uint8_t spawn_stack[4096 ];
791+
792+ int
793+ do_spawn (void *ptr) {
794+ struct spawn_info *pinfo = (struct spawn_info *)ptr;
795+
796+ /* Ensure that the memory server is always on fd 4 */
797+ if (pinfo->memserver != 4 ) {
798+ dup2 (pinfo->memserver , 4 );
799+ close (pinfo->memserver );
800+ }
801+
802+ /* Clear the signal mask */
803+ sigset_t mask;
804+ sigfillset (&mask);
805+ sigprocmask (SIG_UNBLOCK, &mask, NULL );
806+
807+ return execvpe (pinfo->path , pinfo->argv , pinfo->envp );
808+ }
809+
810+ int
811+ safe_spawn (pid_t *ppid, const char *path, int memserver,
812+ char * const argv[], char * const envp[])
813+ {
814+ struct spawn_info info = { path, argv, envp, memserver };
815+
816+ /* The CLONE_VFORK is *required* because info is on the stack; we don't
817+ want to return until *after* the subprocess has called execvpe(). */
818+ int ret = clone (do_spawn, spawn_stack + sizeof (spawn_stack),
819+ CLONE_VFORK|CLONE_VM, &info);
820+ if (ret < 0 )
821+ return ret;
822+
823+ close (memserver);
824+
825+ *ppid = ret;
826+ return 0 ;
827+ }
828+ #endif // defined(__linux__)
829+
776830#endif // SWIFT_BACKTRACE_ON_CRASH_SUPPORTED
777831
778832} // namespace
@@ -796,13 +850,93 @@ _swift_isThunkFunction(const char *mangledName) {
796850 return ctx.isThunkSymbol (mangledName);
797851}
798852
853+ // Try to demangle a symbol.
854+ SWIFT_RUNTIME_STDLIB_SPI char *
855+ _swift_backtrace_demangle (const char *mangledName,
856+ size_t mangledNameLength,
857+ char *outputBuffer,
858+ size_t *outputBufferSize,
859+ int *status) {
860+ llvm::StringRef name = llvm::StringRef (mangledName, mangledNameLength);
861+
862+ // You must provide buffer size if you're providing your own output buffer
863+ if (outputBuffer && !outputBufferSize) {
864+ return nullptr ;
865+ }
866+
867+ if (Demangle::isSwiftSymbol (name)) {
868+ // This is a Swift mangling
869+ auto options = DemangleOptions::SimplifiedUIDemangleOptions ();
870+ auto result = Demangle::demangleSymbolAsString (name, options);
871+ size_t bufferSize;
872+
873+ if (outputBufferSize) {
874+ bufferSize = *outputBufferSize;
875+ *outputBufferSize = result.length () + 1 ;
876+ }
877+
878+ if (outputBuffer == nullptr ) {
879+ outputBuffer = (char *)::malloc (result.length () + 1 );
880+ bufferSize = result.length () + 1 ;
881+ }
882+
883+ size_t toCopy = std::min (bufferSize - 1 , result.length ());
884+ ::memcpy (outputBuffer, result.data(), toCopy);
885+ outputBuffer[toCopy] = ' \0 ' ;
886+
887+ *status = 0 ;
888+ return outputBuffer;
889+ #ifndef _WIN32
890+ } else if (name.startswith (" _Z" )) {
891+ // Try C++
892+ size_t resultLen;
893+ char *result = abi::__cxa_demangle (mangledName, nullptr , &resultLen, status);
894+
895+ if (result) {
896+ size_t bufferSize;
897+
898+ if (outputBufferSize) {
899+ bufferSize = *outputBufferSize;
900+ *outputBufferSize = resultLen;
901+ }
902+
903+ if (outputBuffer == nullptr ) {
904+ return result;
905+ }
906+
907+ size_t toCopy = std::min (bufferSize - 1 , resultLen - 1 );
908+ ::memcpy (outputBuffer, result, toCopy);
909+ outputBuffer[toCopy] = ' \0 ' ;
910+
911+ free (result);
912+
913+ *status = 0 ;
914+ return outputBuffer;
915+ }
916+ #else
917+ // On Windows, the mangling is different.
918+ // ###TODO: Call __unDName()
919+ #endif
920+ } else {
921+ *status = -2 ;
922+ }
923+
924+ return nullptr ;
925+ }
926+
799927// N.B. THIS FUNCTION MUST BE SAFE TO USE FROM A CRASH HANDLER. On Linux
800928// and macOS, that means it must be async-signal-safe. On Windows, there
801929// isn't an equivalent notion but a similar restriction applies.
802930SWIFT_RUNTIME_STDLIB_INTERNAL bool
931+ #ifdef __linux__
932+ _swift_spawnBacktracer (const ArgChar * const *argv, int memserver_fd)
933+ #else
803934_swift_spawnBacktracer (const ArgChar * const *argv)
935+ #endif
804936{
805- #if TARGET_OS_OSX || TARGET_OS_MACCATALYST
937+ #if !SWIFT_BACKTRACE_ON_CRASH_SUPPORTED
938+ return false ;
939+ #elif TARGET_OS_OSX || TARGET_OS_MACCATALYST || defined(__linux__)
806940 pid_t child;
807941 const char *env[BACKTRACE_MAX_ENV_VARS + 1 ];
808942
@@ -817,10 +951,16 @@ _swift_spawnBacktracer(const ArgChar * const *argv)
817951
818952 // SUSv3 says argv and envp are "completely constant" and that the reason
819953 // posix_spawn() et al use char * const * is for compatibility.
954+ #ifdef __linux__
955+ int ret = safe_spawn (&child, swiftBacktracePath, memserver_fd,
956+ const_cast <char * const *>(argv),
957+ const_cast <char * const *>(env));
958+ #else
820959 int ret = posix_spawn (&child, swiftBacktracePath,
821960 &backtraceFileActions, &backtraceSpawnAttrs,
822961 const_cast <char * const *>(argv),
823962 const_cast <char * const *>(env));
963+ #endif
824964 if (ret < 0 )
825965 return false ;
826966
@@ -835,10 +975,7 @@ _swift_spawnBacktracer(const ArgChar * const *argv)
835975
836976 return false ;
837977
838- // ###TODO: Linux
839978 // ###TODO: Windows
840- #else
841- return false ;
842979#endif
843980}
844981
0 commit comments