xref: /netbsd-src/external/gpl3/gcc/dist/libphobos/libdruntime/core/runtime.d (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 /**
2  * The runtime module exposes information specific to the D runtime code.
3  *
4  * Copyright: Copyright Sean Kelly 2005 - 2009.
5  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
6  * Authors:   Sean Kelly
7  * Source:    $(LINK2 https://github.com/dlang/druntime/blob/master/src/core/runtime.d, _runtime.d)
8  * Documentation: https://dlang.org/phobos/core_runtime.html
9  */
10 
11 /* NOTE: This file has been patched from the original DMD distribution to
12  * work with the GDC compiler.
13  */
14 module core.runtime;
15 
16 version (OSX)
17     version = Darwin;
18 else version (iOS)
19     version = Darwin;
20 else version (TVOS)
21     version = Darwin;
22 else version (WatchOS)
23     version = Darwin;
24 
version(GNU)25 version (GNU)
26 {
27     import gcc.backtrace;
28     // This shouldn't be necessary but ensure that code doesn't get mixed
29     // It does however prevent the unittest SEGV handler to be installed,
30     // which is desireable as it uses backtrace directly.
31     private enum hasExecinfo = false;
32 }
version(DRuntime_Use_Libunwind)33 else version (DRuntime_Use_Libunwind)
34 {
35     import core.internal.backtrace.libunwind;
36     // This shouldn't be necessary but ensure that code doesn't get mixed
37     // It does however prevent the unittest SEGV handler to be installed,
38     // which is desireable as it uses backtrace directly.
39     private enum hasExecinfo = false;
40 }
41 else
42     import core.internal.execinfo;
43 
44 /// C interface for Runtime.loadLibrary
45 extern (C) void* rt_loadLibrary(const char* name);
46 /// ditto
47 version (Windows) extern (C) void* rt_loadLibraryW(const wchar* name);
48 
49 /// C interface for Runtime.unloadLibrary, returns 1/0 instead of bool
50 extern (C) int rt_unloadLibrary(void* ptr);
51 
52 /// C interface for Runtime.initialize, returns 1/0 instead of bool
53 extern(C) int rt_init();
54 /// C interface for Runtime.terminate, returns 1/0 instead of bool
55 extern(C) int rt_term();
56 
57 /**
58  * This type is returned by the module unit test handler to indicate testing
59  * results.
60  */
61 struct UnitTestResult
62 {
63     /**
64      * Number of modules which were tested
65      */
66     size_t executed;
67 
68     /**
69      * Number of modules passed the unittests
70      */
71     size_t passed;
72 
73     /**
74      * Should the main function be run or not? This is ignored if any tests
75      * failed.
76      */
77     bool runMain;
78 
79     /**
80      * Should we print a summary of the results?
81      */
82     bool summarize;
83 
84     /**
85      * Simple check for whether execution should continue after unit tests
86      * have been run. Works with legacy code that expected a bool return.
87      *
88      * Returns:
89      *    true if execution should continue after testing is complete, false if
90      *    not.
91      */
92     bool opCast(T : bool)() const
93     {
94         return runMain && (executed == passed);
95     }
96 
97     /// Simple return code that says unit tests pass, and main should be run
98     enum UnitTestResult pass = UnitTestResult(0, 0, true, false);
99     /// Simple return code that says unit tests failed.
100     enum UnitTestResult fail = UnitTestResult(1, 0, false, false);
101 }
102 
103 /// Legacy module unit test handler
104 alias bool function() ModuleUnitTester;
105 /// Module unit test handler
106 alias UnitTestResult function() ExtendedModuleUnitTester;
107 private
108 {
109     alias bool function(Object) CollectHandler;
110     alias Throwable.TraceInfo function( void* ptr ) TraceHandler;
111 
112     alias void delegate( Throwable ) ExceptionHandler;
113     extern (C) void _d_print_throwable(Throwable t);
114 
115     extern (C) void* thread_stackBottom();
116 }
117 
118 
this()119 shared static this()
120 {
121     // NOTE: Some module ctors will run before this handler is set, so it's
122     //       still possible the app could exit without a stack trace.  If
123     //       this becomes an issue, the handler could be set in C main
124     //       before the module ctors are run.
125     Runtime.traceHandler = &defaultTraceHandler;
126 }
127 
128 
129 ///////////////////////////////////////////////////////////////////////////////
130 // Runtime
131 ///////////////////////////////////////////////////////////////////////////////
132 
133 /**
134  * Stores the unprocessed arguments supplied when the
135  * process was started.
136  */
137 struct CArgs
138 {
139     int argc; /// The argument count.
140     char** argv; /// The arguments as a C array of strings.
141 }
142 
143 /**
144  * This struct encapsulates all functionality related to the underlying runtime
145  * module for the calling context.
146  */
147 struct Runtime
148 {
149     /**
150      * Initializes the runtime.  This call is to be used in instances where the
151      * standard program initialization process is not executed.  This is most
152      * often in shared libraries or in libraries linked to a C program.
153      * If the runtime was already successfully initialized this returns true.
154      * Each call to initialize must be paired by a call to $(LREF terminate).
155      *
156      * Returns:
157      *  true if initialization succeeded or false if initialization failed.
158      */
initialize()159     static bool initialize()
160     {
161         return !!rt_init();
162     }
163 
164     /**
165      * Terminates the runtime.  This call is to be used in instances where the
166      * standard program termination process will not be not executed.  This is
167      * most often in shared libraries or in libraries linked to a C program.
168      * If the runtime was not successfully initialized the function returns false.
169      *
170      * Returns:
171      *  true if termination succeeded or false if termination failed.
172      */
terminate()173     static bool terminate()
174     {
175         return !!rt_term();
176     }
177 
178     /**
179      * Returns the arguments supplied when the process was started.
180      *
181      * Returns:
182      *  The arguments supplied when this process was started.
183      */
184     extern(C) pragma(mangle, "rt_args") static @property string[] args();
185 
186     /**
187      * Returns the unprocessed C arguments supplied when the process was started.
188      * Use this when you need to supply argc and argv to C libraries.
189      *
190      * Returns:
191      *  A $(LREF CArgs) struct with the arguments supplied when this process was started.
192      *
193      * Example:
194      * ---
195      * import core.runtime;
196      *
197      * // A C library function requiring char** arguments
198      * extern(C) void initLibFoo(int argc, char** argv);
199      *
200      * void main()
201      * {
202      *     auto args = Runtime.cArgs;
203      *     initLibFoo(args.argc, args.argv);
204      * }
205      * ---
206      */
207     extern(C) pragma(mangle, "rt_cArgs") static @property CArgs cArgs() @nogc;
208 
209     /**
210      * Locates a dynamic library with the supplied library name and dynamically
211      * loads it into the caller's address space.  If the library contains a D
212      * runtime it will be integrated with the current runtime.
213      *
214      * Params:
215      *  name = The name of the dynamic library to load.
216      *
217      * Returns:
218      *  A reference to the library or null on error.
219      */
loadLibrary()220     static void* loadLibrary()(const scope char[] name)
221     {
222         import core.stdc.stdlib : free, malloc;
223         version (Windows)
224         {
225             import core.sys.windows.winnls : CP_UTF8, MultiByteToWideChar;
226             import core.sys.windows.winnt : WCHAR;
227 
228             if (name.length == 0) return null;
229             // Load a DLL at runtime
230             auto len = MultiByteToWideChar(
231                 CP_UTF8, 0, name.ptr, cast(int)name.length, null, 0);
232             if (len == 0)
233                 return null;
234 
235             auto buf = cast(WCHAR*)malloc((len+1) * WCHAR.sizeof);
236             if (buf is null) return null;
237             scope (exit) free(buf);
238 
239             len = MultiByteToWideChar(
240                 CP_UTF8, 0, name.ptr, cast(int)name.length, buf, len);
241             if (len == 0)
242                 return null;
243 
244             buf[len] = '\0';
245 
246             return rt_loadLibraryW(buf);
247         }
248         else version (Posix)
249         {
250             /* Need a 0-terminated C string for the dll name
251              */
252             immutable len = name.length;
253             auto buf = cast(char*)malloc(len + 1);
254             if (!buf) return null;
255             scope (exit) free(buf);
256 
257             buf[0 .. len] = name[];
258             buf[len] = 0;
259 
260             return rt_loadLibrary(buf);
261         }
262     }
263 
264 
265     /**
266      * Unloads the dynamic library referenced by p.  If this library contains a
267      * D runtime then any necessary finalization or cleanup of that runtime
268      * will be performed.
269      *
270      * Params:
271      *  p = A reference to the library to unload.
272      */
unloadLibrary()273     static bool unloadLibrary()(void* p)
274     {
275         return !!rt_unloadLibrary(p);
276     }
277 
278 
279     /**
280      * Overrides the default trace mechanism with a user-supplied version.  A
281      * trace represents the context from which an exception was thrown, and the
282      * trace handler will be called when this occurs.  The pointer supplied to
283      * this routine indicates the base address from which tracing should occur.
284      * If the supplied pointer is null then the trace routine should determine
285      * an appropriate calling context from which to begin the trace.
286      *
287      * Params:
288      *  h = The new trace handler.  Set to null to disable exception backtracing.
289      */
290     extern(C) pragma(mangle, "rt_setTraceHandler") static @property void traceHandler(TraceHandler h);
291 
292     /**
293      * Gets the current trace handler.
294      *
295      * Returns:
296      *  The current trace handler or null if none has been set.
297      */
298     extern(C) pragma(mangle, "rt_getTraceHandler") static @property TraceHandler traceHandler();
299 
300     /**
301      * Overrides the default collect hander with a user-supplied version.  This
302      * routine will be called for each resource object that is finalized in a
303      * non-deterministic manner--typically during a garbage collection cycle.
304      * If the supplied routine returns true then the object's dtor will called
305      * as normal, but if the routine returns false than the dtor will not be
306      * called.  The default behavior is for all object dtors to be called.
307      *
308      * Params:
309      *  h = The new collect handler.  Set to null to use the default handler.
310      */
311     extern(C) pragma(mangle, "rt_setCollectHandler") static @property void collectHandler( CollectHandler h );
312 
313 
314     /**
315      * Gets the current collect handler.
316      *
317      * Returns:
318      *  The current collect handler or null if none has been set.
319      */
320     extern(C) pragma(mangle, "rt_getCollectHandler") static @property CollectHandler collectHandler();
321 
322 
323     /**
324      * Overrides the default module unit tester with a user-supplied version.
325      * This routine will be called once on program initialization.  The return
326      * value of this routine indicates to the runtime whether the tests ran
327      * without error.
328      *
329      * There are two options for handlers. The `bool` version is deprecated but
330      * will be kept for legacy support. Returning `true` from the handler is
331      * equivalent to returning `UnitTestResult.pass` from the extended version.
332      * Returning `false` from the handler is equivalent to returning
333      * `UnitTestResult.fail` from the extended version.
334      *
335      * See the documentation for `UnitTestResult` to see how you should set up
336      * the return structure.
337      *
338      * See the documentation for `runModuleUnitTests` for how the default
339      * algorithm works, or read the example below.
340      *
341      * Params:
342      *  h = The new unit tester.  Set both to null to use the default unit
343      *  tester.
344      *
345      * Example:
346      * ---------
347      * shared static this()
348      * {
349      *     import core.runtime;
350      *
351      *     Runtime.extendedModuleUnitTester = &customModuleUnitTester;
352      * }
353      *
354      * UnitTestResult customModuleUnitTester()
355      * {
356      *     import std.stdio;
357      *
358      *     writeln("Using customModuleUnitTester");
359      *
360      *     // Do the same thing as the default moduleUnitTester:
361      *     UnitTestResult result;
362      *     foreach (m; ModuleInfo)
363      *     {
364      *         if (m)
365      *         {
366      *             auto fp = m.unitTest;
367      *
368      *             if (fp)
369      *             {
370      *                 ++result.executed;
371      *                 try
372      *                 {
373      *                     fp();
374      *                     ++result.passed;
375      *                 }
376      *                 catch (Throwable e)
377      *                 {
378      *                     writeln(e);
379      *                 }
380      *             }
381      *         }
382      *     }
383      *     if (result.executed != result.passed)
384      *     {
385      *         result.runMain = false;  // don't run main
386      *         result.summarize = true; // print failure
387      *     }
388      *     else
389      *     {
390      *         result.runMain = true;    // all UT passed
391      *         result.summarize = false; // be quiet about it.
392      *     }
393      *     return result;
394      * }
395      * ---------
396      */
extendedModuleUnitTester(ExtendedModuleUnitTester h)397     static @property void extendedModuleUnitTester( ExtendedModuleUnitTester h )
398     {
399         sm_extModuleUnitTester = h;
400     }
401 
402     /// Ditto
moduleUnitTester(ModuleUnitTester h)403     static @property void moduleUnitTester( ModuleUnitTester h )
404     {
405         sm_moduleUnitTester = h;
406     }
407 
408     /**
409      * Gets the current legacy module unit tester.
410      *
411      * This property should not be used, but is supported for legacy purposes.
412      *
413      * Note that if the extended unit test handler is set, this handler will
414      * be ignored.
415      *
416      * Returns:
417      *  The current legacy module unit tester handler or null if none has been
418      *  set.
419      */
moduleUnitTester()420     static @property ModuleUnitTester moduleUnitTester()
421     {
422         return sm_moduleUnitTester;
423     }
424 
425     /**
426      * Gets the current module unit tester.
427      *
428      * This handler overrides any legacy module unit tester set by the
429      * moduleUnitTester property.
430      *
431      * Returns:
432      *  The current  module unit tester handler or null if none has been
433      *  set.
434      */
extendedModuleUnitTester()435     static @property ExtendedModuleUnitTester extendedModuleUnitTester()
436     {
437         return sm_extModuleUnitTester;
438     }
439 
440 private:
441 
442     // NOTE: This field will only ever be set in a static ctor and should
443     //       never occur within any but the main thread, so it is safe to
444     //       make it __gshared.
445     __gshared ExtendedModuleUnitTester sm_extModuleUnitTester = null;
446     __gshared ModuleUnitTester sm_moduleUnitTester = null;
447 }
448 
449 /**
450  * Set source file path for coverage reports.
451  *
452  * Params:
453  *  path = The new path name.
454  * Note:
455  *  This is a dmd specific setting.
456  */
457 extern (C) void dmd_coverSourcePath(string path);
458 
459 /**
460  * Set output path for coverage reports.
461  *
462  * Params:
463  *  path = The new path name.
464  * Note:
465  *  This is a dmd specific setting.
466  */
467 extern (C) void dmd_coverDestPath(string path);
468 
469 /**
470  * Enable merging of coverage reports with existing data.
471  *
472  * Params:
473  *  flag = enable/disable coverage merge mode
474  * Note:
475  *  This is a dmd specific setting.
476  */
477 extern (C) void dmd_coverSetMerge(bool flag);
478 
479 /**
480  * Set the output file name for profile reports (-profile switch).
481  * An empty name will set the output to stdout.
482  *
483  * Params:
484  *  name = file name
485  * Note:
486  *  This is a dmd specific setting.
487  */
488 extern (C) void trace_setlogfilename(string name);
489 
490 /**
491  * Set the output file name for the optimized profile linker DEF file (-profile switch).
492  * An empty name will set the output to stdout.
493  *
494  * Params:
495  *  name = file name
496  * Note:
497  *  This is a dmd specific setting.
498  */
499 extern (C) void trace_setdeffilename(string name);
500 
501 /**
502  * Set the output file name for memory profile reports (-profile=gc switch).
503  * An empty name will set the output to stdout.
504  *
505  * Params:
506  *  name = file name
507  * Note:
508  *  This is a dmd specific setting.
509  */
510 extern (C) void profilegc_setlogfilename(string name);
511 
512 ///////////////////////////////////////////////////////////////////////////////
513 // Overridable Callbacks
514 ///////////////////////////////////////////////////////////////////////////////
515 
516 
517 /**
518  * This routine is called by the runtime to run module unit tests on startup.
519  * The user-supplied unit tester will be called if one has been set,
520  * otherwise all unit tests will be run in sequence.
521  *
522  * If the extended unittest handler is registered, this function returns the
523  * result from that handler directly.
524  *
525  * If a legacy boolean returning custom handler is used, `false` maps to
526  * `UnitTestResult.fail`, and `true` maps to `UnitTestResult.pass`. This was
527  * the original behavior of the unit testing system.
528  *
529  * If no unittest custom handlers are registered, the following algorithm is
530  * executed (the behavior can be affected by the `--DRT-testmode` switch
531  * below):
532  * 1. Execute any unittests present. For each that fails, print the stack
533  *    trace and continue.
534  * 2. If no unittests were present, set summarize to false, and runMain to
535  *    true.
536  * 3. Otherwise, set summarize to true, and runMain to false.
537  *
538  * See the documentation for `UnitTestResult` for details on how the runtime
539  * treats the return value from this function.
540  *
541  * If the switch `--DRT-testmode` is passed to the executable, it can have
542  * one of 3 values:
543  * 1. "run-main": even if unit tests are run (and all pass), runMain is set
544       to true.
545  * 2. "test-or-main": any unit tests present will cause the program to
546  *    summarize the results and exit regardless of the result. This is the
547  *    default.
548  * 3. "test-only", runMain is set to false, even with no tests present.
549  *
550  * This command-line parameter does not affect custom unit test handlers.
551  *
552  * Returns:
553  *   A `UnitTestResult` struct indicating the result of running unit tests.
554  */
runModuleUnitTests()555 extern (C) UnitTestResult runModuleUnitTests()
556 {
557     version (Windows)
558         import core.sys.windows.stacktrace;
559 
560     static if (__traits(compiles, new LibBacktrace(0)))
561     {
562         import core.sys.posix.signal; // segv handler
563 
564         static extern (C) void unittestSegvHandler(int signum, siginfo_t* info, void* ptr)
565         {
566             import core.stdc.stdio;
567             fprintf(stderr, "Segmentation fault while running unittests:\n");
568             fprintf(stderr, "----------------\n");
569 
570             // First frame is LibBacktrace ctor. Second is signal handler,
571             // but include that for now
572             scope bt = new LibBacktrace(1);
573 
574             foreach (size_t i, const(char[]) msg; bt)
575                 fprintf(stderr, "%s\n", msg.ptr ? msg.ptr : "???");
576         }
577 
578         sigaction_t action = void;
579         sigaction_t oldseg = void;
580         sigaction_t oldbus = void;
581 
582         (cast(byte*) &action)[0 .. action.sizeof] = 0;
583         sigfillset(&action.sa_mask); // block other signals
584         action.sa_flags = SA_SIGINFO | SA_RESETHAND;
585         action.sa_sigaction = &unittestSegvHandler;
586         sigaction(SIGSEGV, &action, &oldseg);
587         sigaction(SIGBUS, &action, &oldbus);
588         scope (exit)
589         {
590             sigaction(SIGSEGV, &oldseg, null);
591             sigaction(SIGBUS, &oldbus, null);
592         }
593     }
594     else static if (hasExecinfo)
595     {
596         import core.sys.posix.signal; // segv handler
597 
598         static extern (C) void unittestSegvHandler( int signum, siginfo_t* info, void* ptr ) nothrow
599         {
600             static enum MAXFRAMES = 128;
601             void*[MAXFRAMES]  callstack;
602 
603             auto numframes = backtrace( callstack.ptr, MAXFRAMES );
604             backtrace_symbols_fd( callstack.ptr, numframes, 2 );
605         }
606 
607         sigaction_t action = void;
608         sigaction_t oldseg = void;
609         sigaction_t oldbus = void;
610 
611         (cast(byte*) &action)[0 .. action.sizeof] = 0;
612         sigfillset( &action.sa_mask ); // block other signals
613         action.sa_flags = SA_SIGINFO | SA_RESETHAND;
614         action.sa_sigaction = &unittestSegvHandler;
615         sigaction( SIGSEGV, &action, &oldseg );
616         sigaction( SIGBUS, &action, &oldbus );
617         scope( exit )
618         {
619             sigaction( SIGSEGV, &oldseg, null );
620             sigaction( SIGBUS, &oldbus, null );
621         }
622     }
623 
624     if (Runtime.sm_extModuleUnitTester !is null)
625         return Runtime.sm_extModuleUnitTester();
626     else if (Runtime.sm_moduleUnitTester !is null)
627         return Runtime.sm_moduleUnitTester() ? UnitTestResult.pass : UnitTestResult.fail;
628     UnitTestResult results;
629     foreach ( m; ModuleInfo )
630     {
631         if ( !m )
632             continue;
633         auto fp = m.unitTest;
634         if ( !fp )
635             continue;
636 
637         import core.exception;
638         ++results.executed;
639         try
640         {
641             fp();
642             ++results.passed;
643         }
644         catch ( Throwable e )
645         {
646             if ( typeid(e) == typeid(AssertError) )
647             {
648                 // Crude heuristic to figure whether the assertion originates in
649                 // the unittested module. TODO: improve.
650                 auto moduleName = m.name;
651                 if (moduleName.length && e.file.length > moduleName.length
652                     && e.file[0 .. moduleName.length] == moduleName)
653                 {
654                     import core.stdc.stdio;
655                     printf("%.*s(%llu): [unittest] %.*s\n",
656                         cast(int) e.file.length, e.file.ptr, cast(ulong) e.line,
657                         cast(int) e.message.length, e.message.ptr);
658 
659                     // Exception originates in the same module, don't print
660                     // the stack trace.
661                     // TODO: omit stack trace only if assert was thrown
662                     // directly by the unittest.
663                     continue;
664                 }
665             }
666             // TODO: perhaps indent all of this stuff.
667             _d_print_throwable(e);
668         }
669     }
670 
671     import core.internal.parseoptions : rt_configOption;
672 
673     if (results.passed != results.executed)
674     {
675         // by default, we always print a summary if there are failures.
676         results.summarize = true;
677     }
678     else switch (rt_configOption("testmode", null, false))
679     {
680     case "run-main":
681         results.runMain = true;
682         break;
683     case "test-only":
684         // Never run main, always summarize
685         results.summarize = true;
686         break;
687     case "":
688         // By default, do not run main if tests are present.
689     case "test-or-main":
690         // only run main if there were no tests. Only summarize if we are not
691         // running main.
692         results.runMain = (results.executed == 0);
693         results.summarize = !results.runMain;
694         break;
695     default:
696         assert(0, "Unknown --DRT-testmode option: " ~ rt_configOption("testmode", null, false));
697     }
698 
699     return results;
700 }
701 
702 /**
703  * Get the default `Throwable.TraceInfo` implementation for the platform
704  *
705  * This functions returns a trace handler, allowing to inspect the
706  * current stack trace.
707  *
708  * Params:
709  *   ptr = (Windows only) The context to get the stack trace from.
710  *         When `null` (the default), start from the current frame.
711  *
712  * Returns:
713  *   A `Throwable.TraceInfo` implementation suitable to iterate over the stack,
714  *   or `null`. If called from a finalizer (destructor), always returns `null`
715  *   as trace handlers allocate.
716  */
717 Throwable.TraceInfo defaultTraceHandler( void* ptr = null )
718 {
719     // avoid recursive GC calls in finalizer, trace handlers should be made @nogc instead
720     import core.memory : GC;
721     if (GC.inFinalizer)
722         return null;
723 
724     static if (__traits(compiles, new LibBacktrace(0)))
725     {
726         version (Posix)
727             static enum FIRSTFRAME = 4;
728         else version (Win64)
729             static enum FIRSTFRAME = 4;
730         else
731             static enum FIRSTFRAME = 0;
732         return new LibBacktrace(FIRSTFRAME);
733     }
734     else static if (__traits(compiles, new UnwindBacktrace(0)))
735     {
736         version (Posix)
737             static enum FIRSTFRAME = 5;
738         else version (Win64)
739             static enum FIRSTFRAME = 4;
740         else
741             static enum FIRSTFRAME = 0;
742         return new UnwindBacktrace(FIRSTFRAME);
743     }
version(Windows)744     else version (Windows)
745     {
746         import core.sys.windows.stacktrace;
747         static if (__traits(compiles, new StackTrace(0, null)))
748         {
749             import core.sys.windows.winnt : CONTEXT;
750             version (Win64)
751                 enum FIRSTFRAME = 4;
752             else version (Win32)
753                 enum FIRSTFRAME = 0;
754             return new StackTrace(FIRSTFRAME, cast(CONTEXT*)ptr);
755         }
756         else
757             return null;
758     }
759     else static if (__traits(compiles, new DefaultTraceInfo()))
760         return new DefaultTraceInfo();
761     else
762         return null;
763 }
764 
765 /// Example of a simple program printing its stack trace
766 unittest
767 {
768     import core.runtime;
769     import core.stdc.stdio;
770 
main()771     void main()
772     {
773         auto trace = defaultTraceHandler(null);
774         foreach (line; trace)
775         {
776             printf("%.*s\n", cast(int)line.length, line.ptr);
777         }
778     }
779 }
780 
version(DRuntime_Use_Libunwind)781 version (DRuntime_Use_Libunwind)
782 {
783     import core.internal.backtrace.handler;
784 
785     alias DefaultTraceInfo = LibunwindHandler;
786 }
787 /// Default implementation for most POSIX systems
788 else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInfo
789 {
790     import core.demangle;
791     import core.stdc.stdlib : free;
792     import core.stdc.string : strlen, memchr, memmove;
793 
this()794     this()
795     {
796         // it may not be 1 but it is good enough to get
797         // in CALL instruction address range for backtrace
798         enum CALL_INSTRUCTION_SIZE = 1;
799 
800         static if (__traits(compiles, backtrace((void**).init, int.init)))
801             numframes = cast(int) backtrace(this.callstack.ptr, MAXFRAMES);
802         // Backtrace succeeded, adjust the frame to point to the caller
803         if (numframes >= 2)
804             foreach (ref elem; this.callstack)
805                 elem -= CALL_INSTRUCTION_SIZE;
806         else // backtrace() failed, do it ourselves
807         {
808             static void** getBasePtr()
809             {
810                 version (D_InlineAsm_X86)
811                     asm { naked; mov EAX, EBP; ret; }
812                 else
813                     version (D_InlineAsm_X86_64)
814                         asm { naked; mov RAX, RBP; ret; }
815                 else
816                     return null;
817             }
818 
819             auto  stackTop    = getBasePtr();
820             auto  stackBottom = cast(void**) thread_stackBottom();
821             void* dummy;
822 
823             if ( stackTop && &dummy < stackTop && stackTop < stackBottom )
824             {
825                 auto stackPtr = stackTop;
826 
827                 for ( numframes = 0; stackTop <= stackPtr &&
828                           stackPtr < stackBottom &&
829                           numframes < MAXFRAMES; )
830                 {
831                     callstack[numframes++] = *(stackPtr + 1) - CALL_INSTRUCTION_SIZE;
832                     stackPtr = cast(void**) *stackPtr;
833                 }
834             }
835         }
836     }
837 
opApply(scope int delegate (ref const (char[]))dg)838     override int opApply( scope int delegate(ref const(char[])) dg ) const
839     {
840         return opApply( (ref size_t, ref const(char[]) buf)
841                         {
842                             return dg( buf );
843                         } );
844     }
845 
opApply(scope int delegate (ref size_t,ref const (char[]))dg)846     override int opApply( scope int delegate(ref size_t, ref const(char[])) dg ) const
847     {
848         version (linux) enum enableDwarf = true;
849         else version (FreeBSD) enum enableDwarf = true;
850         else version (DragonFlyBSD) enum enableDwarf = true;
851         else version (OpenBSD) enum enableDwarf = true;
852         else version (Darwin) enum enableDwarf = true;
853         else enum enableDwarf = false;
854 
855         const framelist = backtrace_symbols( callstack.ptr, numframes );
856         scope(exit) free(cast(void*) framelist);
857 
858         static if (enableDwarf)
859         {
860             import core.internal.backtrace.dwarf;
861             return traceHandlerOpApplyImpl(numframes,
862                 i => callstack[i],
863                 (i) { auto str = framelist[i][0 .. strlen(framelist[i])]; return getMangledSymbolName(str); },
864                 dg);
865         }
866         else
867         {
868             int ret = 0;
869             for (size_t pos = 0; pos < numframes; ++pos)
870             {
871                 char[4096] fixbuf = void;
872                 auto buf = framelist[pos][0 .. strlen(framelist[pos])];
873                 buf = fixline( buf, fixbuf );
874                 ret = dg( pos, buf );
875                 if ( ret )
876                     break;
877             }
878             return ret;
879         }
880     }
881 
toString()882     override string toString() const
883     {
884         string buf;
885         foreach ( i, line; this )
886             buf ~= i ? "\n" ~ line : line;
887         return buf;
888     }
889 
890 private:
891     int     numframes;
892     static enum MAXFRAMES = 128;
893     void*[MAXFRAMES]  callstack = void;
894 
895 private:
fixline(const (char)[]buf,return ref char[4096]fixbuf)896     const(char)[] fixline( const(char)[] buf, return ref char[4096] fixbuf ) const
897     {
898         size_t symBeg, symEnd;
899 
900         getMangledSymbolName(buf, symBeg, symEnd);
901 
902         enum min = (size_t a, size_t b) => a <= b ? a : b;
903         if (symBeg == symEnd || symBeg >= fixbuf.length)
904         {
905             immutable len = min(buf.length, fixbuf.length);
906             fixbuf[0 .. len] = buf[0 .. len];
907             return fixbuf[0 .. len];
908         }
909         else
910         {
911             fixbuf[0 .. symBeg] = buf[0 .. symBeg];
912 
913             auto sym = demangle(buf[symBeg .. symEnd], fixbuf[symBeg .. $]);
914 
915             if (sym.ptr !is fixbuf.ptr + symBeg)
916             {
917                 // demangle reallocated the buffer, copy the symbol to fixbuf
918                 immutable len = min(fixbuf.length - symBeg, sym.length);
919                 memmove(fixbuf.ptr + symBeg, sym.ptr, len);
920                 if (symBeg + len == fixbuf.length)
921                     return fixbuf[];
922             }
923 
924             immutable pos = symBeg + sym.length;
925             assert(pos < fixbuf.length);
926             immutable tail = buf.length - symEnd;
927             immutable len = min(fixbuf.length - pos, tail);
928             fixbuf[pos .. pos + len] = buf[symEnd .. symEnd + len];
929             return fixbuf[0 .. pos + len];
930         }
931     }
932 }
933