The OpenD Programming Language

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