lsdbghelper.dll

lsdbghelper.dll is a helper dll that resides in the %ORANGE%\bin directory. When present and in %PATH%, it will be used if a program crashes, to generate a stack trace.
The stack trace will be slightly different, depending on how the program was compiled.

We will use this program, t14.cpp, as an example:

#include <stdio.h>
#include <string.h>
int a1()
{
    int a;
    printf("hi");
//  strcat(0, 0);
    *(char *)0 = 4;
}
int a2()
{
    int a;
    printf("hi");
    a1();
}
int a3()
{
    int a;
    printf("hi");
    a2();
}
int a4()
{
    int a;
    printf("hi");
    a3();
}
main()
{
    printf("hi");
    a4();
}

For a normal compilation, the stack trace will just give addresses. Following is an an example of a program, t14.cpp, with a crash in main():

Access Violation:(C:\orangec\src\occparse\temp\t14.exe)
CS:EIP 0023:00401054  SS:ESP 002B:0019FF18
EAX: 00000002  EBX: 00000000  ECX: 0042CF0C  EDX: 00000000  flags: 00010206
EBP: 0019FF68  ESI: 00000000  EDI: 00401000
 DS:     002B   ES:     002B   FS:     0053   GS:     002B


CS:EIP  C6 05 00 00 00 00 04 33 C0 59 59 59 59 C3 68 0C

Stack trace:
                        401054

Here the first address is where it crashed; this will always be valid. There may be more addresses given if the crash is nested inside multiple function calls. But bear in release mode the compiler aggressively optimizes EBP and this may cause the stack trace to be incomplete.

There may not be more than one address here. Causes could be a crash in an external dll; or it is in main(); or EBP has been used for something other than marking stack frames.

Compiling the program with the compiler switch -pl-mx results in a detailed map file t14.map. The first few lines of the 'Publics By Name' section of the file are as follows:

Publics By Value

401012   startupStruct
40101a   main
401062 X a1()
401075 X a2()
401095 X a3()
4010c2 X a4()
40113c X __startup
401374 X __crtexit

The failing address in the stack trace is between main() and a1(), so, the failure is in the main() you can use a debugger to hone in on exactly where the crash is if you want.

Compiling with /C-E turns off the EBP optimizations, and gives a more accurate stack trace.

To get more detail, compile with -g or /g (debugging) enabled. This will turn off inlining and other optimizations, and make it easier to hone in on the problem.

When t14.cpp is compiled with -g the output is:

Access Violation:(C:\orangec\src\occparse\temp\t14.exe)
CS:EIP 0023:00401029  SS:ESP 002B:0019FEF4
EAX: 00000002  EBX: 00000000  ECX: 0042CF0C  EDX: 00000000  flags: 00010216
EBP: 0019FEF8  ESI: 00000000  EDI: 00401000
 DS:     002B   ES:     002B   FS:     0053   GS:     002B


CS:EIP  C6 05 00 00 00 00 04 8B E5 5D C3 55 8B EC 51 68

Stack trace:
                        401029: a1() + 0xf  module: t14.cpp, line: 8
                        401048: a2() + 0x14  module: t14.cpp, line: 14
                        401060: a3() + 0x14  module: t14.cpp, line: 20
                        401078: a4() + 0x14  module: t14.cpp, line: 26
                        40108f: main + 0x13  module: t14.cpp, line: 31
                        40128f: __startup + 0x1bb

here there are multiple addresses, because compiling with -g turned off inlining and used the expanded versions of the functions.

here you can see that the stack trace has additional information about the crash.

if we want we can look at the map file again (use the -pl-mx compiler switch)

Publics By Value

401012   startupStruct
40101a X a1()
401034 X a2()
40104c X a3()
401064 X a4()
40107c   main

here we can see that the first address, where the crash occurs, fits in the a1() function.