Thread overview
how to debug exceptions/asserts thrown in module constructors?
Nov 27, 2016
Timothee Cour
Nov 27, 2016
timotheecour
Nov 28, 2016
Basile B.
Nov 28, 2016
Basile B.
November 27, 2016
in the process of trying to debug https://github.com/BlackEdder/ggplotd/issues/32 I would like to get a stracktrace and/or put a breakpoint before exception is thrown:


```
lldb $binary
r
(lldb)
Process 34168 resuming
object.Exception@../../../../.dub/packages/gtk-d-3.3.1/gtk-d/src/gtkc/Loader.d(123):
Library load failed: libatk-1.0.dylib
Process 34168 exited with status = 1 (0x00000001)
```

Adding
```
b _d_throwc #does nothing
```

didn't help, also, it hasn't entered d main yet so `Runtime.traceHandler = &defaultTraceHandler;` isn't helpful.

The fix here was to lookup the code, find the corresponding mangled name location and add a breakpoint via `b _D4gtkc6Loader6Linker11loadLibraryFAyaZv` but is there a general fix?


November 27, 2016
UPDATE:

* b Loader.d:123 didn't help either:

error: parsing line table prologue at 0x00000000 (parsing ended around 0x00000000
Breakpoint 1: where = mybinary.temp`D4gtkc6Loader6Linker12_staticDtor3FZv, address = 0x0000000100315410
(process exited despite breakpoint); dmd's dwarf debug info seems incorrect

* b _d_throwc #does nothing

* b _d_print_throwable: doesn't show useful context (only shows backtrace after stack unwinding)
(lldb) bt
* thread #1: tid = 0x6187c1, 0x0000000100191c30 mybinary.temp _d_print_throwable, stop reason = breakpoint 4.1
  * frame #0: 0x0000000100191c30 mybinary.temp _d_print_throwable
    frame #1: 0x0000000100191530 mybinary.temp rt_init + 160
    frame #2: 0x0000000100191a9a mybinary.temp D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZv + 14
    frame #3: 0x0000000100191a40 mybinary.temp D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv + 36
    frame #4: 0x00000001001919a6 mybinary.temp _d_run_main + 498
    frame #5: 0x0000000100001efa mybinary.temp main + 34
    frame #6: 0x00007fff89ad65ad libdyld.dylib start + 1

* b _D4gtkc6Loader6Linker11loadLibraryFAyaZv isn't very helpful since this function is complex (and could be inlined more generally) and that function is called many times before the exception is thrown
```
  public static void loadLibrary(string library)
  {
    void* handle = pLoadLibrary(library);

    //TODO: A more general way to try more than one version.
    if ( handle is null && library == importLibs[LIBRARY.GSV] )
      handle = pLoadLibrary(importLibs[LIBRARY.GSV1]);

    if ( handle is null )
      throw new Exception("Library load failed: " ~ library);

    loadedLibraries[library] = handle;
  }
```

but at least we get a better context:

(lldb) bt
* thread #1: tid = 0x6187c1, 0x0000000100315878 mybinary.temp D4gtkc6Loader6Linker11loadLibraryFAyaZv, stop reason = breakpoint 3.1
  * frame #0: 0x0000000100315878 mybinary.temp D4gtkc6Loader6Linker11loadLibraryFAyaZv
    frame #1: 0x0000000100315699 mybinary.temp D4gtkc6Loader6Linker9getSymbolFAyaAAyaXPv + 237
    frame #2: 0x00000001003155a4 mybinary.temp D4gtkc6Loader6Linker9getSymbolFAyaAE4gtkc5paths7LIBRARYXPv + 232
    frame #3: 0x00000001003163bd mybinary.temp D4gtkc6Loader6Linker39__T4linkTPUZE4gtkc12gobjecttypes5GTypeZ4linkFKPUZE4gtkc12gobjecttypes5GTypeAyaAE4gtkc5paths7LIBRARYXv + 69 at .dub/packages/gtk-d-3.3.1/gtk-d/src/gtkc/Loader.d:46
    frame #4: 0x000000010038c75d mybinary.temp D4gtkc3atk18_sharedStaticCtor4FZv + 77 at .dub/packages/gtk-d-3.3.1/gtk-d/src/gtkc/atk.d:36
    frame #5: 0x000000010038c67d mybinary.temp _D4gtkc3atk15__modsharedctorFZv + 9 at .dub/packages/gtk-d-3.3.1/gtk-d/src/gtkc/atk.d:32
    frame #6: 0x0000000100199c17 mybinary.temp D2rt5minfo67__T14runModuleFuncsS442rt5minfo11ModuleGroup8runCtorsMFZ9__lambda2Z14runModuleFuncsMFAxPyS6object10ModuleInfoZv + 91
    frame #7: 0x0000000100199785 mybinary.temp D2rt5minfo11ModuleGroup8runCtorsMFZv + 37
    frame #8: 0x0000000100199a91 mybinary.temp D2rt5minfo13rt_moduleCtorUZ14__foreachbody1MFKS2rt19sections_osx_x86_6412SectionGroupZi + 45
    frame #9: 0x0000000100199a60 mybinary.temp rt_moduleCtor + 20
    frame #10: 0x00000001001914f3 mybinary.temp rt_init + 99
    frame #11: 0x0000000100191a9a mybinary.temp D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZv + 14
    frame #12: 0x0000000100191a40 mybinary.temp D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv + 36
    frame #13: 0x00000001001919a6 mybinary.temp _d_run_main + 498
    frame #14: 0x0000000100001efa mybinary.temp main + 34
    frame #15: 0x00007fff89ad65ad libdyld.dylib start + 1


Ideally there should be a way (via a runtime or compile time option) to wrap the exception throwing (during rt_moduleCtor) inside a extern(C) function that we can put a breakpoint on (and possibly even call backtrace_symbols on)



////////
to reproduce:

main.d:
import ggplotd.gtk;
void main(){
}


dub.json:
{
 "targetType": "executable",
 "sourcePaths":["."],

 "dependencies": {
 "ggplotd": ">=1.1.0",
 },

 "subConfigurations": {
  "ggplotd": "ggplotd-gtk",
 },
 "buildRequirements": ["allowWarnings"],
}
November 28, 2016
On Sunday, 27 November 2016 at 22:19:26 UTC, Timothee Cour wrote:
> Adding
> ```
> b _d_throwc #does nothing
> ```

Try instead "b _d_throwdwarf". Changes made earlier this year to EH made _d_throwc obsolete. The equivalent is now _d_throwdwarf. Don't ask me why I wouldn't be able to answer.
November 28, 2016
On Monday, 28 November 2016 at 02:52:02 UTC, Basile B. wrote:
> On Sunday, 27 November 2016 at 22:19:26 UTC, Timothee Cour wrote:
>> Adding
>> ```
>> b _d_throwc #does nothing
>> ```
>
> Don't ask me why I wouldn't be able to answer.

The only thing that I can say is that it's probably related to one of the big change of the year in DMD, i.e C++ interfacing, that led W.Bright to change some stuff to EH.