jrfonseca / drmingw

Postmortem debugging tools for MinGW.
GNU Lesser General Public License v2.1
273 stars 53 forks source link

ExcHndl.dll can't print the crash call stack under Windows 7 #71

Closed asmwarrior closed 1 year ago

asmwarrior commented 1 year ago

Hi, we use the drmingw-0.9.1-win64(exchndl.dll) in Code::Blocks(we build it from Msys2/MinGW GCC) to catch/report the crash. Thanks for the great tool.

While, we found some issue when using this tool under Windows7 (64bit).

The first thing is: Under Windows 7, the latest usable version is 0.9.1. I did some test:

drmingw-0.9.5-win64, does not work, no call stack crash report.
drmingw-0.9.4-win64, does not work, no call stack crash report.
drmingw-0.9.3-win64, I can't start C::B if I use this dll, it report some api-ms-win-downlevel-kernel32-l2-1-0.dll is missing
drmingw-0.9.2-win64, it works, but not the full call stack is printed, I got only two lines of call stack
drmingw-0.9.1-win64, it works, the full call stack is printed

The second thing is: please note that when using drmingw-0.9.1-win64, we can't see the line information is printed when the full call stack is reported. (The dll and exe were all containing the debug information)

The full discussion is here in our Code::Blocks forum: error alert message when using ThreadSearch Plugin

Thanks.

jrfonseca commented 1 year ago

This is likely related to #55, but perhaps there's more going on as I think that issue was fixed, and the versions/symptoms reported above don't line up exactly.

An easy experiment to make here is to try drmingw-0.9.x's drmingw.exe/mgwhelp.dll/exchndl.dll with drmingw-0.9.1's dbghelp.dll symsrv.dll. This will enable tease apart whether the regression is the newer dbghelp DLLs, or some code change in drmingw itself.

asmwarrior commented 1 year ago

This is likely related to #55, but perhaps there's more going on as I think that issue was fixed, and the versions/symptoms reported above don't line up exactly.

An easy experiment to make here is to try drmingw-0.9.x's drmingw.exe/mgwhelp.dll/exchndl.dll with drmingw-0.9.1's dbghelp.dll symsrv.dll. This will enable tease apart whether the regression is the newer dbghelp DLLs, or some code change in drmingw itself.

Hi, thanks for the response.

I just tried your mentioned experiment.

1, drmingw-0.9.5 files + drmingw-0.9.1's dbghelp.dll symsrv.dll  ------> I make C::B crash, but no RPT file generated/updated.
2, drmingw-0.9.4 files + drmingw-0.9.1's dbghelp.dll symsrv.dll  ------> I make C::B crash, but no RPT file generated/updated.

So, it looks like the regression is inside drmingw itself?

asmwarrior commented 1 year ago

This is likely related to #55, but perhaps there's more going on as I think that issue was fixed, and the versions/symptoms reported above don't line up exactly.

I think the #55 is already fixed. From my test, C::B started correctly when loading drmingw-0.9.5 or drmingw-0.9.4 supplied exchndl.dll.

asmwarrior commented 1 year ago

I did some further test, I keep the file: dbgcore.dll, dbghelp.dll, symsrv.dll and symsrv.yes file from drmingw-0.9.1-win64 package unchanged.

Then, I have using the addr2line.exe , catchsegv.exe , drmingw.exe, exchndl.dll and mgwhelp.dll from either drmingw-0.9.0-win64 and drmingw-0.8.2-win64, they can both catch and print the call stack in the RPT file, but still no line information.

My guess is maybe the GCC has changed and your are using the mismatched libbfd library, and this library can't decode the line information?

When I test a dll with debug information or without debug information, if I got the call stack, I see the call stack is the same, so my guess is that the debug information is not used by drmingw?

jrfonseca commented 1 year ago

Thanks for those experiments.

We no longer use libbfd. We use libdwarf instead. But I agree with your assessment -- the problem is not using symbols.

Looking at the changes in range, my suspicion goes to bd80ec248c90832a440e9f33bed4c4a77508f8ed, namely the MgwSymFromAddr chunk about _using pe_findsymbol() first. Maybe C::B is adding PE symbols, but too few to be of any use.

Could you please attach a zip with an executable compiled with C::B which I can easily reproduce the issue using addr2line? It would save me time and quickly focus on the issue.

asmwarrior commented 1 year ago

Hi, I did a simple test for the latest version 0.9.5

1, I install the drmingw through the pacman command under msys2's mingw64

pacman -S mingw-w64-x86_64-drmingw

2, I create a simple console project under C::B, the content is just the file named "/mingw64/share/drmingw/sample/sample.cpp"

3, I set the drmingw.exe as the jit debugger, and run the built exe file, when it crashed, the drmingw.exe jump out, and I see it has line information in the drmingw.exe's report window.

drmingw_test.exe caused an Access Violation at location 000000013FAB585F in module drmingw_test.exe Writing to location 0000000000000001.

AddrPC           Params
000000013FAB585F 0000000000000000 000000013FABD002 000000000024FD10  drmingw_test.exe!__mingw_sformat+0x2f5f  [C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/stdio/mingw_vfscanf.c @ 1122]
000000013FAB6668 0000000000000001 0000000013010012 0000000000000000  drmingw_test.exe!__mingw_vsscanf+0x38  [C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/stdio/mingw_vfscanf.c @ 1630]
000000013FABB347 000000013FABD003 000000013FABD000 0000000000000001  drmingw_test.exe!sscanf+0x37  [D:/code/drmingw_test/main.cpp @ 294]
000000013FAB1563 0000000000000008 4016666660000000 000000013FABD009  drmingw_test.exe!Function+0x33  [D:/code/drmingw_test/main.cpp @ 12]
    10: 
    11: static void Function(int i, double j, const char * pszString) {
>   12:     sscanf("12345", "%i", (int *)1);
    13: }
    14: 
000000013FABB390 0000000100000004 5297B68240B33333 00000000003086A0  drmingw_test.exe!Class::StaticMethod+0x30  [D:/code/drmingw_test/main.cpp @ 17]
    15: struct Class {
    16:     static void StaticMethod(int i, float j) {
>   17:         Function(i * 2, j, "Hello");
    18:     }
    19: 
000000013FABB3BE 000000000024FDBF 000000013FAB14F9 0000000000308688  drmingw_test.exe!Class::Method+0x1e  [D:/code/drmingw_test/main.cpp @ 21]
    19: 
    20:     void Method(void) {
>   21:         StaticMethod(4, 5.6f);
    22:     }
    23: };
000000013FAB1588 0000000000000000 0000000000000030 000000013FAC1050  drmingw_test.exe!main+0x1e  [D:/code/drmingw_test/main.cpp @ 28]
    26:     ExcHndlInit();
    27:     Class instance;
>   28:     instance.Method();
    29:     return 0;
    30: }
000000013FAB13AE 0000000000000000 0000000000000000 0000000000000000  drmingw_test.exe!__tmainCRTStartup+0x22e  [C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c @ 329]
000000013FAB14E6 0000000000000000 0000000000000000 0000000000000000  drmingw_test.exe!mainCRTStartup+0x16  [C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c @ 206]
0000000076B4556D 0000000000000000 0000000000000000 0000000000000000  kernel32.dll!BaseThreadInitThunk+0xd
0000000076DA385D 0000000000000000 0000000000000000 0000000000000000  ntdll.dll!RtlUserThreadStart+0x1d

This means drmingw can catch the call stack and print the line information.

What I reported issue is that a plugin crashed inside C::B, and drmingw can't catch the crash.

I guess the difference is that when running the sample from "/mingw64/share/drmingw/sample/sample.cpp", it is a single thread application. Which my original reported issue is that the crash happens in a worker thread.

I will try to create a crash app which the crash point is in a worker thread.

asmwarrior commented 1 year ago

I made another example, which I make the crash in a worker thread:

/* Public Domain.
 *
 * A sample C++ program for Dr.MinGW.
 */

#include <stdio.h>
#include <stdlib.h>

#include "exchndl.h"

#include <string>
#include <iostream>
#include <thread>

using namespace std;

static void Function(int i, double j, const char * pszString) {
    sscanf("12345", "%i", (int *)1);
}

struct Class {
    static void StaticMethod(int i, float j) {
        Function(i * 2, j, "Hello");
    }

    void Method(void) {
        StaticMethod(4, 5.6f);
    }
};

// The function we want to execute on the new thread.
void task1(string msg)
{
    cout << "task1 says: " << msg;
    Class instance;
    instance.Method();
}

int main()
{

    ExcHndlInit();

    // Constructs the new thread and runs it. Does not block execution.
    thread t1(task1, "Hello");

    // Do other things...

    // Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
    t1.join();
}

when I run the generated app, I got the correct line and call stack in the drmingw gui, see below:

drmingw_test.exe caused an Access Violation at location 000000013F225A3F in module drmingw_test.exe Writing to location 0000000000000001.

AddrPC           Params
000000013F225A3F 0000000000000000 000000013F22E002 00000000025EF770  drmingw_test.exe!__mingw_sformat+0x2f5f  [C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/stdio/mingw_vfscanf.c @ 1122]
000000013F226848 000007FEFD4F2AB0 0000000000000005 0000000000000005  drmingw_test.exe!__mingw_vsscanf+0x38  [C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/stdio/mingw_vfscanf.c @ 1630]
000000013F22B527 000000013F22E003 000000013F22E000 0000000000000001  drmingw_test.exe!sscanf+0x37  [D:/code/drmingw_test/main.cpp @ 294]
000000013F221563 0000000000000008 4016666660000000 000000013F22E009  drmingw_test.exe!Function+0x33  [D:/code/drmingw_test/main.cpp @ 20]
    18: 
    19: static void Function(int i, double j, const char * pszString) {
>   20:     sscanf("12345", "%i", (int *)1);
    21: }
    22: 
000000013F22B570 0000000000000004 0000000040B33333 0000000000000000  drmingw_test.exe!Class::StaticMethod+0x30  [D:/code/drmingw_test/main.cpp @ 297]
000000013F22B59E 00000000025EF81F 0000000000000018 00000005003A0022  drmingw_test.exe!Class::Method+0x1e  [D:/code/drmingw_test/main.cpp @ 297]
000000013F2215AA 00000000025EF850 000000013F22E009 00000000025EF87F  drmingw_test.exe!task1+0x40  [D:/code/drmingw_test/main.cpp @ 42]
    40:     cout << "task1 says: " << msg;
    41:     Class instance;
>   42:     instance.Method();
    43: }
    44: 
000000013F22C029 00000000003D8750 00000000003D8748 00000000003D8750  drmingw_test.exe!std::__invoke_impl<void, void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*>+0x59  [D:/code/drmingw_test/main.cpp @ 297]
000000013F22C1DC 00000000003D8750 00000000003D8748 00000000025EF9F0  drmingw_test.exe!std::__invoke<void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*>+0x3c  [F:/msys2/mingw64/include/c++/12.1.0/bits/std_thread.h @ 175]
   173:     bool
   174:     joinable() const noexcept
>  175:     { return !(_M_id == id()); }
   176: 
   177:     void
000000013F22BC45 00000000003D8748 000007FEEA872C56 FFFFFFFFFFFFFFFF  drmingw_test.exe!std::thread::_Invoker<std::tuple<void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*> >::_M_invoke<0ull, 1ull>+0x45  [D:/code/drmingw_test/main.cpp @ 297]
000000013F22BC68 00000000003D8748 FFFFFFFFFFFFFFFF 0000000000000000  drmingw_test.exe!std::thread::_Invoker<std::tuple<void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*> >::operator()+0x18  [D:/code/drmingw_test/main.cpp @ 297]
000000013F22BACC 00000000003D8740 0000000000000000 0000000000000000  drmingw_test.exe!std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*> > >::_M_run+0x1c  [D:/code/drmingw_test/main.cpp @ 297]
000007FEA9ACBE8F 000000000033F2D8 0000000000000000 000000000033F490  libstdc++-6.dll!atomic_flag_test_and_set_explicit+0x19f
000007FEEA874B4B 000000000033F2A0 0000000000000000 0000000000000000  libwinpthread-1.dll!pthread_create_wrapper+0x9b
000007FEFD46415F 000007FEFD4F1EA0 000000000033F490 0000000000000000  msvcrt.dll!srand+0x93
000007FEFD466EBD 0000000000000000 0000000000000000 0000000000000000  msvcrt.dll!_ftime64_s+0x1dd
0000000076B4556D 0000000000000000 0000000000000000 0000000000000000  kernel32.dll!BaseThreadInitThunk+0xd
0000000076DA385D 0000000000000000 0000000000000000 0000000000000000  ntdll.dll!RtlUserThreadStart+0x1d

The interesting thing is: if I "rename" the main.cpp to "main6666.cpp", and I see drmingw can't find the main.cpp file, and the crash report shown in drmingw gui looks like below, though the line information is still there.

drmingw_test.exe caused an Access Violation at location 000000013F985A3F in module drmingw_test.exe Writing to location 0000000000000001.

AddrPC           Params
000000013F985A3F 0000000000000000 000000013F98E002 00000000027DF4C0  drmingw_test.exe!__mingw_sformat+0x2f5f  [C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/stdio/mingw_vfscanf.c @ 1122]
000000013F986848 000007FEFD4F2AB0 0000000000000005 0000000000000005  drmingw_test.exe!__mingw_vsscanf+0x38  [C:/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/stdio/mingw_vfscanf.c @ 1630]
000000013F98B527 000000013F98E003 000000013F98E000 0000000000000001  drmingw_test.exe!sscanf+0x37  [D:/code/drmingw_test/main.cpp @ 294]
000000013F981563 0000000000000008 4016666660000000 000000013F98E009  drmingw_test.exe!Function+0x33  [D:/code/drmingw_test/main.cpp @ 20]
000000013F98B570 0000000000000004 0000000040B33333 0000000000000000  drmingw_test.exe!Class::StaticMethod+0x30  [D:/code/drmingw_test/main.cpp @ 297]
000000013F98B59E 00000000027DF56F 0000000000000018 00000005003A0022  drmingw_test.exe!Class::Method+0x1e  [D:/code/drmingw_test/main.cpp @ 297]
000000013F9815AA 00000000027DF5A0 000000013F98E009 00000000027DF5CF  drmingw_test.exe!task1+0x40  [D:/code/drmingw_test/main.cpp @ 42]
000000013F98C029 00000000007F8750 00000000007F8748 00000000007F8750  drmingw_test.exe!std::__invoke_impl<void, void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*>+0x59  [D:/code/drmingw_test/main.cpp @ 297]
000000013F98C1DC 00000000007F8750 00000000007F8748 00000000027DF740  drmingw_test.exe!std::__invoke<void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*>+0x3c  [F:/msys2/mingw64/include/c++/12.1.0/bits/std_thread.h @ 175]
   173:     bool
   174:     joinable() const noexcept
>  175:     { return !(_M_id == id()); }
   176: 
   177:     void
000000013F98BC45 00000000007F8748 000007FEF97F2C56 FFFFFFFFFFFFFFFF  drmingw_test.exe!std::thread::_Invoker<std::tuple<void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*> >::_M_invoke<0ull, 1ull>+0x45  [D:/code/drmingw_test/main.cpp @ 297]
000000013F98BC68 00000000007F8748 FFFFFFFFFFFFFFFF 0000000000000000  drmingw_test.exe!std::thread::_Invoker<std::tuple<void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*> >::operator()+0x18  [D:/code/drmingw_test/main.cpp @ 297]
000000013F98BACC 00000000007F8740 0000000000000000 0000000000000000  drmingw_test.exe!std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), char const*> > >::_M_run+0x1c  [D:/code/drmingw_test/main.cpp @ 297]
000007FEA9ACBE8F 000000000013F2D8 0000000000000000 000000000013F490  libstdc++-6.dll!atomic_flag_test_and_set_explicit+0x19f
000007FEF97F4B4B 000000000013F2A0 0000000000000000 0000000000000000  libwinpthread-1.dll!pthread_create_wrapper+0x9b
000007FEFD46415F 000007FEFD4F1EA0 000000000013F490 0000000000000000  msvcrt.dll!srand+0x93
000007FEFD466EBD 0000000000000000 0000000000000000 0000000000000000  msvcrt.dll!_ftime64_s+0x1dd
0000000076B4556D 0000000000000000 0000000000000000 0000000000000000  kernel32.dll!BaseThreadInitThunk+0xd
0000000076DA385D 0000000000000000 0000000000000000 0000000000000000  ntdll.dll!RtlUserThreadStart+0x1d

Note that all the test is done in Windows 7 64bit and the msys2's latest 64bit mingw64 compiler, and the drmingw 0.9.5 . Which means I can't reproduce the issue (a plugin crashed the C::B).

I really don't know how to give more tests, because reproduce my original issue involving the whole C::B and the testing C::B project is too complex. But I can't reproduce the issue in a simple single thread or multi thread application.

jrfonseca commented 1 year ago

I see. If the remaining C::B issue is specific to multiple threads, then this is a known limitation, as mentioned on https://github.com/jrfonseca/drmingw/issues/54

That said, nothing changed in this respect since version 0.9.1. So I don't see how come 0.9.1 worked, but now it does not...

jrfonseca commented 1 year ago

So it seems the issue is more subtle than any reasons advanced so far.

Ideally I'd reproduce the issue myself with C::B and investigate the issue. I tried to download C::B release/nighly binaries, but neither seems to contain any debug symbols. Getting C::B to crash is easy -- patching the codeblocks.{exe,dll} by inserting CC / INT3 machine code on a carefully chosen function does the trick. But debug symbols are a must, and I can't really afford to figure out how to build C::B. Perhaps split-debug symbols .debug could be provided with nightly builds?

Another solution is for you, @asmwarrior, to git bisect drmingw history, while replacing dbghelp.dll and friends with 0.9.1's DLLs, and figure out which commit broke C::B. If building drmingw is tricky, you can always temporary clone DrMinGW to a personal repos, and then push tags for every commit to test, and download the binaries from GitHub built through GitHub Actions.

asmwarrior commented 1 year ago

Hi, jrfonseca, thanks for the response.

Building C::B is not easy, it need a self built wx library, and you have other tweaks here and there.

I think the issue can be divided to parts:

1, the C::B crash can't be caught, I mean 0.9.1 can catch the crash, but the later version can't catch the crash. 2, once the crash get caught, the call stack dose not contains the line information, I mean 0.9.1's call stack report does not have line information, I have tested the C::B I build myself and have all the debug information in the exe and dll files.

About the github action, I haven't used this tool before, I just noticed that you have tag the 0.9.6 in your git repo, and I see github action was running, but I really don't know how to download the generated file(If I'm correctly, it called the artifact file).

Thanks.

asmwarrior commented 1 year ago

I found a very interesting thing, I was set the drmingw 0.9.5 as a jit debugger, and under C::B I was still use the exchndl.dll version 0.9.1.

Test1: I try to reproduce the same crash as I reported before under C::B, and I first found that under C::B folder, I got the RPT file contains the call-stack of the crashed thread(only one thread), this is the expect behavior, and after the crash, jit debugger Dr.MinGW 0.9.5 Window jump out, and I see it shows the call-stack of all threads.

Test2: Now, I did another test, because in Test1, the plugin dll is stripped(no debug information), I replaced the dll with an unstripped dll, and make the crash again. This time, I see the RPT file under C::B still contains the call-stack of the crashed thread, but unluckily, there is no line information. While, the good news is, the jumped out the jit drmingw 0.9.5 debugger's window shows the call stacks with line information. So, I guess the drmingw 0.9.5 is at least better than 0.9.1 to read the drawf info.

asmwarrior commented 1 year ago

I found a very interesting thing, I was set the drmingw 0.9.5 as a jit debugger, and under C::B I was still use the exchndl.dll version 0.9.1.

Test1: I try to reproduce the same crash as I reported before under C::B, and I first found that under C::B folder, I got the RPT file contains the call-stack of the crashed thread(only one thread), this is the expect behavior, and after the crash, jit debugger Dr.MinGW 0.9.5 Window jump out, and I see it shows the call-stack of all threads.

Test2: Now, I did another test, because in Test1, the plugin dll is stripped(no debug information), I replaced the dll with an unstripped dll, and make the crash again. This time, I see the RPT file under C::B still contains the call-stack of the crashed thread, but unluckily, there is no line information. While, the good news is, the jumped out the jit drmingw 0.9.5 debugger's window shows the call stacks with line information. So, I guess the drmingw 0.9.5 is at least better than 0.9.1 to read the drawf info.

While, I did another test:

I just replaced the exchndl.dll file (in the same folder as codeblocks.exe) from 0.9.1 to 0.9.5, and I make the same crash as in Test2, the result is: I don't see any thing written to the RPT file, which means the embedded exchndl.dll 0.9.5 does not work, but the jump out jit debugger 0.9.5 windows shows the call stack and line information correctly as the Test2.

asmwarrior commented 1 year ago

It looks build drmingw is a bit hard for me.

I clone the repo and update all the submodules.

Now, if I run cmake under msys2's mingw64 shell, I first got the "WinDBG" not found error. My question is: How can I disable this? I think I don't need it because I mainly handle the MinGW GCC generated exe and dlls.

So, I comment out the line in the CMakeLists.txt

find_package(windbg)

Now, here comes another issue:

/f/code/drmingw/build
# cmake ../ -G"MinGW Makefiles"
-- The C compiler identification is GNU 12.1.0
-- The CXX compiler identification is GNU 12.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: F:/msys2/mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: F:/msys2/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test HAVE_STATIC_LIBGCC_FLAG
-- Performing Test HAVE_STATIC_LIBGCC_FLAG - Success
-- Performing Test HAVE_STATIC_LIBSTDCXX_FLAG
-- Performing Test HAVE_STATIC_LIBSTDCXX_FLAG - Success
CMake Error at CMakeLists.txt:80 (message):
  Win32 threads required.

-- objcopy version: 2.38
-- Configuring incomplete, errors occurred!
See also "F:/code/drmingw/build/CMakeFiles/CMakeOutput.log".

I really don't know how to fix this issue, it looks like I have to enable the option "POSIX_THREADS"

This make the local building of drmingw a bit hard.

BTW: I just read this: https://github.com/jrfonseca/drmingw/blob/master/BUILD.md

It said the windbg is recommended, what does recommende mean? is it optional?

EDIT: This is the method I used under msys2's mingw64 shell, hope it will help others.

cmake ../ -G"MinGW Makefiles" -DPOSIX_THREADS=1
mingw32-make
asmwarrior commented 1 year ago

Hi, I think I have found the reason of this issue.

I just add many MessageBox function call in the source file exchndl.cpp.

I first found that the crash is correctly found by the event handler.

And later, I found that the report file is wrong here.

Setup(void)
{
    MessageBox(NULL,"1","Setup",MB_OK);
    setDumpCallback(writeReport);

    // Figure out what the report file will be named, and store it away
    DWORD nSize = MAX_PATH;
    std::vector<char> path(nSize);
    DWORD dwRet;
    while ((dwRet = GetModuleFileNameA(nullptr, &path[0], nSize)) == nSize) {
        nSize *= 2;
        path.resize(nSize);
    }
    if (dwRet) {
        // Look for the '.' before the "EXE" extension.  Replace the extension
        // with "RPT"
        path.resize(nSize);
        auto found = std::find(path.crbegin(), path.crend(), '.');
        if (found != path.crend()) {
            path.resize(found - path.crbegin());
        }
        path.push_back('.');
        path.push_back('R');
        path.push_back('P');
        path.push_back('T');
        g_szLogFileName.replace(g_szLogFileName.begin(), g_szLogFileName.end(), &path[0],
                                path.size());
        MessageBox(NULL,g_szLogFileName.c_str(),"Setup",MB_OK);
    } else {
        g_szLogFileName = "EXCHNDL.RPT";
    }
}

When this message jump out

MessageBox(NULL,g_szLogFileName.c_str(),"Setup",MB_OK);

I see the content of the messagebox is:

---------------------------
Setup
---------------------------
F:\code\cb-64bit\codeblocks.exe
---------------------------
确定   
---------------------------

So, you see, the expected log file name should be:

F:\code\cb-64bit\codeblocks.RPT

That's why the report file does not contains the crash report.

asmwarrior commented 1 year ago

This is my test code to see where the problem is:


#include <algorithm>
#include <string>
#include <vector>

#include "Windows.h"

using namespace std;

int main()
{

    std::string str_path_org = "F:\\code\\cb-64bit\\codeblocks.exe";
    int nSize = str_path_org.size();
    std::vector<char> path(str_path_org.begin(), str_path_org.end());

    std::string g_szLogFileName = str_path_org;

        // Look for the '.' before the "EXE" extension.  Replace the extension
        // with "RPT"
        path.resize(nSize);
        auto found = std::find(path.crbegin(), path.crend(), '.');
        if (found != path.crend()) {
            path.resize(found - path.crbegin());
        }
        path.push_back('.');
        path.push_back('R');
        path.push_back('P');
        path.push_back('T');
        g_szLogFileName.replace(g_szLogFileName.begin(), g_szLogFileName.end(), &path[0],
                                path.size());
        MessageBox(NULL,g_szLogFileName.c_str(),"Setup",MB_OK);
}

It looks like this line:

path.resize(found - path.crbegin());

is not correct.

In my test code

found - path.crbegin() == 3

What I guess is that we need a

path.crend() - found - 1

Anyway, I think the code is still complex to understand.

asmwarrior commented 1 year ago

With the above mentioned changes in the source file exchndl.cpp, I now got the F:\code\cb-64bit\codeblocks.RPT correctly shown the crash call stack with line information!

I'm testing the latest git master, which shows the version is 0.9.6.

jrfonseca commented 1 year ago

@asmwarrior, apologies for the silence. I'm currently abroad and have no spare time. Thanks for the further investigation and updates. At a glance, it makes sense. I thought I had a test to prevent this, but I now realize my tests all call ExcHndlSetLogFileNameA hence never hit this code. That too needs fixing. I'll look deeper into this when I'm back.

asmwarrior commented 1 year ago

OK, Thanks for the reply. I'm not sure why using a byte array is OK here, but from my point of view, a string or wstring is better to handle those file path find and replace task.

It looks strange that this issue happens for at least several years, and it looks like no other guys see or report it.

Another thing is that Code::Blocks ship this tool, and I hope you will release a new version drmingw, so that we can update our old 0.9.1 version.

Thanks.

asmwarrior commented 1 year ago

@jrfonseca any progress about this issue?

jrfonseca commented 1 year ago

Fixed now. I'll make a new release shortly too.