52
52
#include < cstring>
53
53
#include < cerrno>
54
54
55
+ #ifdef _WIN32
56
+ // We'll probably want dbghelp.h here
57
+ #else
58
+ #include < cxxabi.h>
59
+ #endif
60
+
55
61
#define DEBUG_BACKTRACING_SETTINGS 0
56
62
57
63
#ifndef lengthof
@@ -70,7 +76,7 @@ SWIFT_RUNTIME_STDLIB_INTERNAL BacktraceSettings _swift_backtraceSettings = {
70
76
// enabled
71
77
#if TARGET_OS_OSX
72
78
OnOffTty::TTY,
73
- #elif 0 // defined(__linux__) || defined(_WIN32)
79
+ #elif defined(__linux__) // || defined(_WIN32)
74
80
OnOffTty::On,
75
81
#else
76
82
OnOffTty::Off,
@@ -80,7 +86,7 @@ SWIFT_RUNTIME_STDLIB_INTERNAL BacktraceSettings _swift_backtraceSettings = {
80
86
true ,
81
87
82
88
// interactive
83
- #if TARGET_OS_OSX // || defined(__linux__) || defined(_WIN32)
89
+ #if TARGET_OS_OSX || defined(__linux__) // || defined(_WIN32)
84
90
OnOffTty::TTY,
85
91
#else
86
92
OnOffTty::Off,
@@ -773,6 +779,54 @@ _swift_backtraceSetupEnvironment()
773
779
*penv = 0 ;
774
780
}
775
781
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
+
776
830
#endif // SWIFT_BACKTRACE_ON_CRASH_SUPPORTED
777
831
778
832
} // namespace
@@ -796,13 +850,109 @@ _swift_isThunkFunction(const char *mangledName) {
796
850
return ctx.isThunkSymbol (mangledName);
797
851
}
798
852
853
+ // / Try to demangle a symbol.
854
+ // /
855
+ // / Unlike other entry points that do this, we try both Swift and C++ here.
856
+ // /
857
+ // / @param mangledName is the symbol name to be demangled.
858
+ // / @param mangledNameLength is the length of this name.
859
+ // / @param outputBuffer is a pointer to a buffer in which to place the result.
860
+ // / @param outputBufferSize points to a variable that will be filled in with
861
+ // / the size of the allocated buffer (NOT the length of the result).
862
+ // / @param status returns the status codes defined in the C++ ABI.
863
+ // /
864
+ // / If outputBuffer and outputBufferSize are both nullptr, this function will
865
+ // / allocate memory for the result using malloc().
866
+ // /
867
+ // / If outputBuffer is nullptr but outputBufferSize is not, the function will
868
+ // / fill outputBufferSize with the required buffer size and return nullptr.
869
+ // /
870
+ // / Otherwise, the result will be written into the output buffer, and the
871
+ // / size of the result will be written into outputBufferSize. If the buffer
872
+ // / is too small, the result will be truncated, but outputBufferSize will
873
+ // / still be set to the number of bytes that would have been required to
874
+ // / copy out the full result (including a trailing NUL).
875
+ // /
876
+ // / @returns `true` if demangling was successful.
877
+ SWIFT_RUNTIME_STDLIB_SPI char *
878
+ _swift_backtrace_demangle (const char *mangledName,
879
+ size_t mangledNameLength,
880
+ char *outputBuffer,
881
+ size_t *outputBufferSize,
882
+ int *status) {
883
+ llvm::StringRef name = llvm::StringRef (mangledName, mangledNameLength);
884
+
885
+ if (Demangle::isSwiftSymbol (name)) {
886
+ // This is a Swift mangling
887
+ auto options = DemangleOptions::SimplifiedUIDemangleOptions ();
888
+ auto result = Demangle::demangleSymbolAsString (name, options);
889
+ size_t bufferSize;
890
+
891
+ if (outputBufferSize) {
892
+ bufferSize = *outputBufferSize;
893
+ *outputBufferSize = result.length () + 1 ;
894
+ }
895
+
896
+ if (outputBuffer == nullptr ) {
897
+ outputBuffer = (char *)::malloc (result.length () + 1 );
898
+ bufferSize = result.length () + 1 ;
899
+ }
900
+
901
+ size_t toCopy = std::min (bufferSize - 1 , result.length ());
902
+ ::memcpy (outputBuffer, result.data(), toCopy);
903
+ outputBuffer[toCopy] = ' \0 ' ;
904
+
905
+ *status = 0 ;
906
+ return outputBuffer;
907
+ #ifndef _WIN32
908
+ } else if (name.startswith (" _Z" )) {
909
+ // Try C++
910
+ size_t resultLen;
911
+ char *result = abi::__cxa_demangle (mangledName, nullptr , &resultLen, status);
912
+
913
+ if (result) {
914
+ size_t bufferSize;
915
+
916
+ if (outputBufferSize) {
917
+ bufferSize = *outputBufferSize;
918
+ *outputBufferSize = resultLen;
919
+ }
920
+
921
+ if (outputBuffer == nullptr ) {
922
+ return result;
923
+ }
924
+
925
+ size_t toCopy = std::min (bufferSize - 1 , resultLen - 1 );
926
+ ::memcpy (outputBuffer, result, toCopy);
927
+ outputBuffer[toCopy] = ' \0 ' ;
928
+
929
+ *status = 0 ;
930
+ return outputBuffer;
931
+ }
932
+ #else
933
+ // On Windows, the mangling is different.
934
+ // ###TODO: Call __unDName()
935
+ #endif
936
+ } else {
937
+ *status = -2 ;
938
+ }
939
+
940
+ return nullptr ;
941
+ }
942
+
799
943
// N.B. THIS FUNCTION MUST BE SAFE TO USE FROM A CRASH HANDLER. On Linux
800
944
// and macOS, that means it must be async-signal-safe. On Windows, there
801
945
// isn't an equivalent notion but a similar restriction applies.
802
946
SWIFT_RUNTIME_STDLIB_INTERNAL bool
947
+ #ifdef __linux__
948
+ _swift_spawnBacktracer (const ArgChar * const *argv, int memserver_fd)
949
+ #else
803
950
_swift_spawnBacktracer (const ArgChar * const *argv)
951
+ #endif
804
952
{
805
- #if TARGET_OS_OSX || TARGET_OS_MACCATALYST
953
+ #if !SWIFT_BACKTRACE_ON_CRASH_SUPPORTED
954
+ return false ;
955
+ #elif TARGET_OS_OSX || TARGET_OS_MACCATALYST || defined(__linux__)
806
956
pid_t child;
807
957
const char *env[BACKTRACE_MAX_ENV_VARS + 1 ];
808
958
@@ -817,10 +967,16 @@ _swift_spawnBacktracer(const ArgChar * const *argv)
817
967
818
968
// SUSv3 says argv and envp are "completely constant" and that the reason
819
969
// posix_spawn() et al use char * const * is for compatibility.
970
+ #ifdef __linux__
971
+ int ret = safe_spawn (&child, swiftBacktracePath, memserver_fd,
972
+ const_cast <char * const *>(argv),
973
+ const_cast <char * const *>(env));
974
+ #else
820
975
int ret = posix_spawn (&child, swiftBacktracePath,
821
976
&backtraceFileActions, &backtraceSpawnAttrs,
822
977
const_cast <char * const *>(argv),
823
978
const_cast <char * const *>(env));
979
+ #endif
824
980
if (ret < 0 )
825
981
return false ;
826
982
@@ -835,10 +991,7 @@ _swift_spawnBacktracer(const ArgChar * const *argv)
835
991
836
992
return false ;
837
993
838
- // ###TODO: Linux
839
994
// ###TODO: Windows
840
- #else
841
- return false ;
842
995
#endif
843
996
}
844
997
0 commit comments