Author Topic: Debugger plugin issue when I click the "Setp into instruction"  (Read 3326 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Debugger plugin issue when I click the "Setp into instruction"
« on: January 12, 2019, 02:26:31 am »
Hi, when debugging, I click the "Step into instruction", then the debugger plugin just has no further response. The whole C::B is still active without hanging.

Here is the debug log:
Code: [Select]
[debug]> next
[debug]E:\code\gdb-debug1\main.cpp:9:119:beg:0x401586
[debug]>>>>>>cb_gdb:

At E:\code\gdb-debug1\main.cpp:9

[debug]> if 1
disassemble 0x401586
info frame
end
[debug] > > >


This happens in the latest nightly 64bit C::B and a self build 32 bit C::B.
The GDB I'm using is: either 64bit GDB 8.1 or GDB 20190111(git head) version build myself.
Any ideas.

EDIT:
This issue also happens when you have "Disassmbler" window opened.
« Last Edit: January 12, 2019, 02:28:51 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #1 on: January 12, 2019, 02:51:05 am »
Here is the log I run GDB under command line:
Code: [Select]
D:\code\gdb-test\bin\Debug>gdb gdb-test.exe
D:\code\gdbmybuild\bin\gdb.exe: warning: Couldn't determine a path for the index cache directory.
GNU gdb (GDB) 8.2.50.20190111-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "mingw32".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gdb-test.exe...
(gdb) b main.cpp:10
Breakpoint 1 at 0x401649: file main.cpp, line 10.
(gdb) r
Starting program: D:\code\gdb-test\bin\Debug\gdb-test.exe
[New Thread 6572.0x16c4]
Do you need "set solib-search-path" or "set sysroot"?
Hello world!

Breakpoint 1, main () at main.cpp:10
10          int b = 0;
(gdb) stepi
11          a++;
(gdb) nexti
12          a= a+6;
(gdb) disas
Dump of assembler code for function main():
   0x00401600 <+0>:     lea    0x4(%esp),%ecx
   0x00401604 <+4>:     and    $0xfffffff0,%esp
   0x00401607 <+7>:     pushl  -0x4(%ecx)
   0x0040160a <+10>:    push   %ebp
   0x0040160b <+11>:    mov    %esp,%ebp
   0x0040160d <+13>:    push   %ecx
   0x0040160e <+14>:    sub    $0x24,%esp
   0x00401611 <+17>:    call   0x401870 <__main>
   0x00401616 <+22>:    movl   $0x404045,0x4(%esp)
   0x0040161e <+30>:    movl   $0x6ff05a00,(%esp)
   0x00401625 <+37>:    call   0x4016d4 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc>
   0x0040162a <+42>:    movl   $0x4016dc,(%esp)
   0x00401631 <+49>:    mov    %eax,%ecx
   0x00401633 <+51>:    call   0x4016f4 <_ZNSolsEPFRSoS_E>
   0x00401638 <+56>:    sub    $0x4,%esp
   0x0040163b <+59>:    movl   $0x0,-0xc(%ebp)
   0x00401642 <+66>:    movl   $0x3,-0xc(%ebp)
   0x00401649 <+73>:    movl   $0x0,-0x10(%ebp)
   0x00401650 <+80>:    addl   $0x1,-0xc(%ebp)
=> 0x00401654 <+84>:    addl   $0x6,-0xc(%ebp)
   0x00401658 <+88>:    mov    -0xc(%ebp),%eax
   0x0040165b <+91>:    add    $0x1,%eax
   0x0040165e <+94>:    mov    %eax,-0x10(%ebp)
   0x00401661 <+97>:    addl   $0x1,-0x10(%ebp)
   0x00401665 <+101>:   addl   $0x4,-0x10(%ebp)
   0x00401669 <+105>:   mov    $0x0,%eax
   0x0040166e <+110>:   mov    -0x4(%ebp),%ecx
   0x00401671 <+113>:   leave
   0x00401672 <+114>:   lea    -0x4(%ecx),%esp
   0x00401675 <+117>:   ret
End of assembler dump.
(gdb) if 1
 >disassemble 0x00401650
 >info frame
 >end
Dump of assembler code for function main():
   0x00401600 <+0>:     lea    0x4(%esp),%ecx
   0x00401604 <+4>:     and    $0xfffffff0,%esp
   0x00401607 <+7>:     pushl  -0x4(%ecx)
   0x0040160a <+10>:    push   %ebp
   0x0040160b <+11>:    mov    %esp,%ebp
   0x0040160d <+13>:    push   %ecx
   0x0040160e <+14>:    sub    $0x24,%esp
   0x00401611 <+17>:    call   0x401870 <__main>
   0x00401616 <+22>:    movl   $0x404045,0x4(%esp)
   0x0040161e <+30>:    movl   $0x6ff05a00,(%esp)
   0x00401625 <+37>:    call   0x4016d4 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc>
   0x0040162a <+42>:    movl   $0x4016dc,(%esp)
   0x00401631 <+49>:    mov    %eax,%ecx
   0x00401633 <+51>:    call   0x4016f4 <_ZNSolsEPFRSoS_E>
   0x00401638 <+56>:    sub    $0x4,%esp
   0x0040163b <+59>:    movl   $0x0,-0xc(%ebp)
   0x00401642 <+66>:    movl   $0x3,-0xc(%ebp)
   0x00401649 <+73>:    movl   $0x0,-0x10(%ebp)
   0x00401650 <+80>:    addl   $0x1,-0xc(%ebp)
=> 0x00401654 <+84>:    addl   $0x6,-0xc(%ebp)
   0x00401658 <+88>:    mov    -0xc(%ebp),%eax
   0x0040165b <+91>:    add    $0x1,%eax
   0x0040165e <+94>:    mov    %eax,-0x10(%ebp)
   0x00401661 <+97>:    addl   $0x1,-0x10(%ebp)
   0x00401665 <+101>:   addl   $0x4,-0x10(%ebp)
   0x00401669 <+105>:   mov    $0x0,%eax
   0x0040166e <+110>:   mov    -0x4(%ebp),%ecx
   0x00401671 <+113>:   leave
   0x00401672 <+114>:   lea    -0x4(%ecx),%esp
   0x00401675 <+117>:   ret
End of assembler dump.
Stack level 0, frame at 0x28fed0:
 eip = 0x401654 in main (main.cpp:12); saved eip = 0x4013eb
 source language c++.
 Arglist at 0x28feb8, args:
 Locals at 0x28feb8, Previous frame's sp is 0x28fed0
 Saved registers:
  ebp at 0x28feb8, eip at 0x28fecc
(gdb)
And Here is the test code:
Code: [Select]
#include <iostream>

using namespace std;

int main()
{
    cout << "Hello world!" << endl;
    int a = 0;
    a = 3;
    int b = 0;
    a++;
    a= a+6;
    b = a+1;
    b++;
    b = b+4;
    return 0;
}

So, I guess it is a C::B related issue.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #2 on: January 12, 2019, 08:50:28 am »
OK, I debugged for a while, in this function call: void GDB_driver::ParseOutput(const wxString& output)

The argument L" > > >" is the output from GDB. so maybe C::B thought there are still some GDB command user has to enter.
Code: [Select]
[debug]#0  GDB_driver::ParseOutput (this=0xbdb7450, output=L" > > >") at D:\code\cb\cb_sf_git\clean-trunk-for-commit\src\plugins\debuggergdb\gdb_driver.cpp:693
[debug]#1  0x67d4ff17 in DebuggerGDB::ParseOutput (this=0x72da698, output=L" > > >") at D:\code\cb\cb_sf_git\clean-trunk-for-commit\src\plugins\debuggergdb\debuggergdb.cpp:1740
[debug]#2  0x67d51866 in DebuggerGDB::OnGDBOutput (this=0x72da698, event=...) at D:\code\cb\cb_sf_git\clean-trunk-for-commit\src\plugins\debuggergdb\debuggergdb.cpp:1879
[debug]#3  0x66482d92 in wxAppConsoleBase::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)(wxEvent&), wxEvent&) const () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#4  0x66483267 in wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#5  0x665d9bde in wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#6  0x665d9d2a in wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#7  0x665da431 in wxEvtHandler::TryHereOnly(wxEvent&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#8  0x665da49a in wxEvtHandler::ProcessEventLocally(wxEvent&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#9  0x665da4f3 in wxEvtHandler::ProcessEvent(wxEvent&) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#10 0x665dbb53 in wxEvtHandler::ProcessPendingEvents() () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#11 0x66484b40 in wxAppConsoleBase::ProcessPendingEvents() () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#12 0x664b6328 in wxEventLoopManual::ProcessEvents() () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#13 0x664b63fd in wxEventLoopManual::DoRun() () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#14 0x664b6103 in wxEventLoopBase::Run() () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#15 0x664881b4 in wxAppConsoleBase::MainLoop() () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#16 0x00404dae in CodeBlocksApp::OnRun (this=0x3bde520) at D:\code\cb\cb_sf_git\clean-trunk-for-commit\src\src\app.cpp:870
[debug]#17 0x664fe3b1 in wxEntryReal(int&, wchar_t**) () from D:\code\wxWidgets-3.1.2\lib\gcc_dll\wxmsw312u_gcc_cb.dll
[debug]#18 0x004021db in WinMain@16 (hInstance=0x400000, hPrevInstance=0x0, nCmdShow=10) at D:\code\cb\cb_sf_git\clean-trunk-for-commit\src\src\app.cpp:338
[debug]#19 0x0050644d in main ()

The bad thing is: after this "GDB_driver::ParseOutput" function call, I never see another function call, which means the GDB prompt string never returned? :( If that's true, the problem is hard to solve.

EDIT:
If I paste the below command to the GDB command line, I see the GDB prompt correctly returned.
Code: [Select]
if 1
disassemble 0x00401650
info frame
end


See the log:
Code: [Select]
Breakpoint 1, main () at main.cpp:10
10          int b = 0;
(gdb) if 1
 >disassemble 0x00401650
 >info frame
 >end
Dump of assembler code for function main():
   0x00401600 <+0>:     lea    0x4(%esp),%ecx
   0x00401604 <+4>:     and    $0xfffffff0,%esp
   0x00401607 <+7>:     pushl  -0x4(%ecx)
   0x0040160a <+10>:    push   %ebp
   0x0040160b <+11>:    mov    %esp,%ebp
   0x0040160d <+13>:    push   %ecx
   0x0040160e <+14>:    sub    $0x24,%esp
   0x00401611 <+17>:    call   0x401870 <__main>
   0x00401616 <+22>:    movl   $0x404045,0x4(%esp)
   0x0040161e <+30>:    movl   $0x6ff05a00,(%esp)
   0x00401625 <+37>:    call   0x4016d4 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc>
   0x0040162a <+42>:    movl   $0x4016dc,(%esp)
   0x00401631 <+49>:    mov    %eax,%ecx
   0x00401633 <+51>:    call   0x4016f4 <_ZNSolsEPFRSoS_E>
   0x00401638 <+56>:    sub    $0x4,%esp
   0x0040163b <+59>:    movl   $0x0,-0xc(%ebp)
   0x00401642 <+66>:    movl   $0x3,-0xc(%ebp)
=> 0x00401649 <+73>:    movl   $0x0,-0x10(%ebp)
   0x00401650 <+80>:    addl   $0x1,-0xc(%ebp)
   0x00401654 <+84>:    addl   $0x6,-0xc(%ebp)
   0x00401658 <+88>:    mov    -0xc(%ebp),%eax
   0x0040165b <+91>:    add    $0x1,%eax
   0x0040165e <+94>:    mov    %eax,-0x10(%ebp)
   0x00401661 <+97>:    addl   $0x1,-0x10(%ebp)
   0x00401665 <+101>:   addl   $0x4,-0x10(%ebp)
   0x00401669 <+105>:   mov    $0x0,%eax
   0x0040166e <+110>:   mov    -0x4(%ebp),%ecx
   0x00401671 <+113>:   leave
   0x00401672 <+114>:   lea    -0x4(%ecx),%esp
   0x00401675 <+117>:   ret
End of assembler dump.
Stack level 0, frame at 0x28fed0:
 eip = 0x401649 in main (main.cpp:10); saved eip = 0x4013eb
 source language c++.
 Arglist at 0x28feb8, args:
 Locals at 0x28feb8, Previous frame's sp is 0x28fed0
 Saved registers:
  ebp at 0x28feb8, eip at 0x28fecc
(gdb)


« Last Edit: January 12, 2019, 09:09:39 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 11899
    • Travis build status
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #3 on: January 12, 2019, 11:37:41 am »
The problem is not step into instruction, but the disassembly command. For some reason I don't know it is broken on windows. If you can debug it and understand why it happens it would be good.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #4 on: January 12, 2019, 03:23:28 pm »
The problem is not step into instruction, but the disassembly command. For some reason I don't know it is broken on windows. If you can debug it and understand why it happens it would be good.

I found that the cause happens that we send several command to GDB separated by \n does not works.
If I change the code:
Code: [Select]
src/plugins/debuggergdb/gdb_commands.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/plugins/debuggergdb/gdb_commands.h b/src/plugins/debuggergdb/gdb_commands.h
index 65bc040e..18901b96 100644
--- a/src/plugins/debuggergdb/gdb_commands.h
+++ b/src/plugins/debuggergdb/gdb_commands.h
@@ -1496,21 +1496,21 @@ class GdbCmd_DisassemblyInit : public DebuggerCmd
             m_disassemblyFlavor(disassemblyFlavor),
             m_hexAddrStr(hexAddrStr)
         {
-            m_Cmd << _T("if 1\n") ;
+            //m_Cmd << _T("if 1\n") ;
             if(m_hexAddrStr.empty())
             {
                 const Cursor &cursor = driver->GetCursor() ;
                 if(cursor.address.empty())
-                    m_Cmd << _T("disassemble $pc,$pc+50\n") ;
+                    m_Cmd << _T("disassemble $pc,$pc+50\n") ;
                 else
                 {
-                    m_Cmd << _T("disassemble ") << cursor.address << _T("\n") ;
+                    m_Cmd << _T("disassemble ") << cursor.address;// << _T("\n") ;
                 }
             }
             else
-                m_Cmd << _T("disassemble ") << m_hexAddrStr << _T("\n") ;
+                m_Cmd << _T("disassemble ") << m_hexAddrStr;// << _T("\n") ;
 
-            m_Cmd << _T("info frame\n") << _T("end");
+            //m_Cmd << _T("info frame\n") << _T("end");
         };
 
         void ParseOutput(const wxString& p_output)

Then, I see only one gdb command(the disassemble command) was send to GDB, and I see GDB can correctly print the disassemble result.
While, if we send the whole command like:
Code: [Select]
if 1\ndisassemble 0x00401650\ninfo frame\nend\n
Then GDB doesn't print the disassembled result, and only the three "> > >" was returned, and the GDB prompt is lost. I believe this time, GDB has some internal issue to handle the multiple commands.

So, I think it is not easy to fix such issue in C::B side. Unless we send command several times.

« Last Edit: January 12, 2019, 03:28:37 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 11899
    • Travis build status
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #5 on: January 12, 2019, 07:34:20 pm »
What happens if you replace \n with the \r\n?
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #6 on: January 13, 2019, 02:21:18 am »
What happens if you replace \n with the \r\n?
I have already tried this yesterday, but this does not solve the issue.

Now, I have tried another patch:
Code: [Select]
src/plugins/debuggergdb/gdb_commands.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/plugins/debuggergdb/gdb_commands.h b/src/plugins/debuggergdb/gdb_commands.h
index 65bc040e..448ea977 100644
--- a/src/plugins/debuggergdb/gdb_commands.h
+++ b/src/plugins/debuggergdb/gdb_commands.h
@@ -1496,21 +1496,21 @@ class GdbCmd_DisassemblyInit : public DebuggerCmd
             m_disassemblyFlavor(disassemblyFlavor),
             m_hexAddrStr(hexAddrStr)
         {
-            m_Cmd << _T("if 1\n") ;
+            //m_Cmd << _T("if 1\r\n") ;
             if(m_hexAddrStr.empty())
             {
                 const Cursor &cursor = driver->GetCursor() ;
                 if(cursor.address.empty())
-                    m_Cmd << _T("disassemble $pc,$pc+50\n") ;
+                    m_Cmd << _T("disassemble $pc,$pc+50\r\n") ;
                 else
                 {
-                    m_Cmd << _T("disassemble ") << cursor.address << _T("\n") ;
+                    m_Cmd << _T("disassemble ") << cursor.address<< _T("\r\n") ;
                 }
             }
             else
-                m_Cmd << _T("disassemble ") << m_hexAddrStr << _T("\n") ;
+                m_Cmd << _T("disassemble ") << m_hexAddrStr;// << _T("\r\n") ;
 
-            m_Cmd << _T("info frame\n") << _T("end");
+            m_Cmd << _T("info frame\r\n");// << _T("end");
         };
 
         void ParseOutput(const wxString& p_output)

Which I remove the "if 1" and "end" command.
It looks like this works:
Code: [Select]
[debug]>>>>>>cb_gdb:

At D:\code\gdb-test\main.cpp:13

[debug]> bt 30
[debug]#0  main () at main.cpp:13
[debug]>>>>>>cb_gdb:
[debug]> disassemble 0x401658
info frame

[debug]Dump of assembler code for function main():
[debug]   0x00401600 <+0>: lea    0x4(%esp),%ecx
[debug]   0x00401604 <+4>: and    $0xfffffff0,%esp
[debug]   0x00401607 <+7>: pushl  -0x4(%ecx)
[debug]   0x0040160a <+10>: push   %ebp
[debug]   0x0040160b <+11>: mov    %esp,%ebp
[debug]   0x0040160d <+13>: push   %ecx
[debug]   0x0040160e <+14>: sub    $0x24,%esp
[debug]   0x00401611 <+17>: call   0x401870 <__main>
[debug]   0x00401616 <+22>: movl   $0x404045,0x4(%esp)
[debug]   0x0040161e <+30>: movl   $0x6ff05a00,(%esp)
[debug]   0x00401625 <+37>: call   0x4016d4 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)>
[debug]   0x0040162a <+42>: movl   $0x4016dc,(%esp)
[debug]   0x00401631 <+49>: mov    %eax,%ecx
[debug]   0x00401633 <+51>: call   0x4016f4 <std::ostream::operator<<(std::ostream& (*)(std::ostream&))>
[debug]   0x00401638 <+56>: sub    $0x4,%esp
[debug]   0x0040163b <+59>: movl   $0x0,-0xc(%ebp)
[debug]   0x00401642 <+66>: movl   $0x3,-0xc(%ebp)
[debug]   0x00401649 <+73>: movl   $0x0,-0x10(%ebp)
[debug]   0x00401650 <+80>: addl   $0x1,-0xc(%ebp)
[debug]   0x00401654 <+84>: addl   $0x6,-0xc(%ebp)
[debug]=> 0x00401658 <+88>: mov    -0xc(%ebp),%eax
[debug]   0x0040165b <+91>: add    $0x1,%eax
[debug]   0x0040165e <+94>: mov    %eax,-0x10(%ebp)
[debug]   0x00401661 <+97>: addl   $0x1,-0x10(%ebp)
[debug]   0x00401665 <+101>: addl   $0x4,-0x10(%ebp)
[debug]   0x00401669 <+105>: mov    $0x0,%eax
[debug]   0x0040166e <+110>: mov    -0x4(%ebp),%ecx
[debug]   0x00401671 <+113>: leave 
[debug]   0x00401672 <+114>: lea    -0x4(%ecx),%esp
[debug]   0x00401675 <+117>: ret   
[debug]End of assembler dump.
[debug]>>>>>>cb_gdb:Stack level 0, frame at 0x28fed0:

Failure finding "Stack level "

[debug] eip = 0x401658 in main (main.cpp:13); saved eip = 0x4013eb
[debug] source language c++.
[debug] Arglist at 0x28feb8, args:
[debug] Locals at 0x28feb8, Previous frame's sp is 0x28fed0
[debug] Saved registers:
[debug]  ebp at 0x28feb8, eip at 0x28fecc
[debug]>>>>>>cb_gdb:Stack level 0, frame at 0x28fed0:
[debug] eip = 0x401658 in main (main.cpp:13); saved eip = 0x4013eb
[debug] source language c++.
[debug] Arglist at 0x28feb8, args:
[debug] Locals at 0x28feb8, Previous frame's sp is 0x28fed0
[debug] Saved registers:
[debug]  ebp at 0x28feb8, eip at 0x28fecc
[debug]>>>>>>cb_gdb:


The GDB prompt returned correctly, but you see the error message from C::B: Failure finding "Stack level ".

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #7 on: January 13, 2019, 09:02:10 am »
The code snippet of the parsing GDB return string is:

Code: [Select]

    static wxString buffer;
    buffer << output << _T('\n');

    m_pDBG->DebugLog(output);

    int idx = buffer.First(GDB_PROMPT);
    const bool foundPrompt = (idx != wxNOT_FOUND);
    if (!foundPrompt)
    {
        // don't uncomment the following line
        // m_ProgramIsStopped is set to false in DebuggerDriver::RunQueue()
//        m_ProgramIsStopped = false;
        return; // come back later
    }

    m_QueueBusy = false;
    int changeFrameAddr = 0 ;
    DebuggerCmd* cmd = CurrentCommand();
    if (cmd)
    {
//        DebugLog(wxString::Format(_T("Command parsing output (cmd: %s): %s"), cmd->m_Cmd.c_str(), buffer.Left(idx).c_str()));
        RemoveTopCommand(false);
        buffer.Remove(idx);
        // remove the '>>>>>>' part of the prompt (or what's left of it)
        int cnt = 6; // max 6 '>'
        while (!buffer.empty() && buffer.Last() == _T('>') && cnt--)
            buffer.RemoveLast();
        if (!buffer.empty() && buffer.Last() == _T('\n'))
            buffer.RemoveLast();
        cmd->ParseOutput(buffer.Left(idx));

        //We do NOT want default output processing for a changed frame as it can result
        //in disassembly being done for a non-current location, since some of the frame
        //response lines are in the pattern of breakpoint output.
        GdbCmd_ChangeFrame *changeFrameCmd = dynamic_cast<GdbCmd_ChangeFrame*>(cmd);
        if (changeFrameCmd)
            changeFrameAddr = changeFrameCmd->AddrChgMode();

        delete cmd;
        RunQueue();
    }
If we send a string which is: disassemble 0x00401650\ninfo frame\n
Then, GDB correctly return TWO prompts. But in the above code, the sub-string before the FIRST prompt is handled, and the whole commands is removed(by the function call RemoveTopCommand(false);).

The idea to fix this is: send the two commands separately, so we will handle the returned string one by one, especially the command was removed one by one.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 11899
    • Travis build status
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #8 on: January 13, 2019, 10:56:41 am »
This won't work. You need to create two separate command objects and then add both of them in the queue. But probably this would make the disassemble command pretty complex.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #9 on: January 13, 2019, 03:53:40 pm »
This won't work. You need to create two separate command objects and then add both of them in the queue. But probably this would make the disassemble command pretty complex.
Yes, that make things more complex.

If we want to run several GDB commands and only return one GDB prompt, I think we need this GDB User-defined commands, see here:
Code: [Select]
ftp://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_188.html
« Last Edit: January 13, 2019, 04:26:04 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 11899
    • Travis build status
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #10 on: January 13, 2019, 04:15:50 pm »
1. You can easily try it, but I'm not sure it will work
2. Your link is broken. You need to add :
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #11 on: January 13, 2019, 04:21:47 pm »
This won't work. You need to create two separate command objects and then add both of them in the queue. But probably this would make the disassemble command pretty complex.
Yes, that make things more complex.

If we want to run several GDB commands and only return one GDB prompt, I think we need this GDB User-defined commands, see here:
Code: [Select]
ftp://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_188.html

OK, I just tested, and it works!

Here is the patch:
Code: [Select]
src/plugins/debuggergdb/gdb_commands.h | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/src/plugins/debuggergdb/gdb_commands.h b/src/plugins/debuggergdb/gdb_commands.h
index 65bc040e..8cac6dde 100644
--- a/src/plugins/debuggergdb/gdb_commands.h
+++ b/src/plugins/debuggergdb/gdb_commands.h
@@ -1496,21 +1496,16 @@ class GdbCmd_DisassemblyInit : public DebuggerCmd
             m_disassemblyFlavor(disassemblyFlavor),
             m_hexAddrStr(hexAddrStr)
         {
-            m_Cmd << _T("if 1\n") ;
             if(m_hexAddrStr.empty())
             {
                 const Cursor &cursor = driver->GetCursor() ;
                 if(cursor.address.empty())
-                    m_Cmd << _T("disassemble $pc,$pc+50\n") ;
+                    m_Cmd << _T("cbdisassemblyinitwithpc") ;
                 else
-                {
-                    m_Cmd << _T("disassemble ") << cursor.address << _T("\n") ;
-                }
+                    m_Cmd << _T("cbdisassemblyinitwitharg ") << cursor.address;
             }
             else
-                m_Cmd << _T("disassemble ") << m_hexAddrStr << _T("\n") ;
-
-            m_Cmd << _T("info frame\n") << _T("end");
+                m_Cmd << _T("cbdisassemblyinitwitharg ") << m_hexAddrStr;
         };
 
         void ParseOutput(const wxString& p_output)


The only thing you need is the load the custom gdb command when your start the debug session:

Code: [Select]
define cbdisassemblyinitwithpc
    disassemble $pc,$pc+50
    info frame
end

define cbdisassemblyinitwitharg
    disassemble $arg0
    info frame
end

For me, I have a personal gdb script file(the file will load the c++ std pretty printer, the wxWidgets' pretty printer), named "my.gdb", which will be loaded when gdb started, so just add the above scripts in the script file.
« Last Edit: January 13, 2019, 04:28:09 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 11899
    • Travis build status
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #12 on: January 13, 2019, 04:28:15 pm »
For me, I have a personal gdb script file(the file will load the c++ std pretty printer, the wxWidgets' pretty printer), named "my.gdb", which will be loaded when gdb started, so just add the above scripts in the script file.
This won't work on users' machines. If you want to commit this you have to add a file to the installation, then add a command to load this file and then apply the above patch. Also some testing on linux is required.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #13 on: January 13, 2019, 04:30:40 pm »
2. Your link is broken. You need to add :
I have updated the link address in the posts, thanks. It looks like the address of the ftp are not shown correctly, so I use the code field to show the raw ftp address.  :)
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5223
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Debugger plugin issue when I click the "Setp into instruction"
« Reply #14 on: January 13, 2019, 05:36:39 pm »
For me, I have a personal gdb script file(the file will load the c++ std pretty printer, the wxWidgets' pretty printer), named "my.gdb", which will be loaded when gdb started, so just add the above scripts in the script file.
This won't work on users' machines. If you want to commit this you have to add a file to the installation, then add a command to load this file and then apply the above patch. Also some testing on linux is required.
Indeed, adding a new file, and let GDB load this file for a normal user is quite complex.

BTW: this patch works without need the extra script file.
Code: [Select]
src/plugins/debuggergdb/gdb_commands.h | 11 +++--------
 src/plugins/debuggergdb/gdb_driver.cpp |  5 +++++
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/plugins/debuggergdb/gdb_commands.h b/src/plugins/debuggergdb/gdb_commands.h
index 65bc040e..8cac6dde 100644
--- a/src/plugins/debuggergdb/gdb_commands.h
+++ b/src/plugins/debuggergdb/gdb_commands.h
@@ -1496,21 +1496,16 @@ class GdbCmd_DisassemblyInit : public DebuggerCmd
             m_disassemblyFlavor(disassemblyFlavor),
             m_hexAddrStr(hexAddrStr)
         {
-            m_Cmd << _T("if 1\n") ;
             if(m_hexAddrStr.empty())
             {
                 const Cursor &cursor = driver->GetCursor() ;
                 if(cursor.address.empty())
-                    m_Cmd << _T("disassemble $pc,$pc+50\n") ;
+                    m_Cmd << _T("cbdisassemblyinitwithpc") ;
                 else
-                {
-                    m_Cmd << _T("disassemble ") << cursor.address << _T("\n") ;
-                }
+                    m_Cmd << _T("cbdisassemblyinitwitharg ") << cursor.address;
             }
             else
-                m_Cmd << _T("disassemble ") << m_hexAddrStr << _T("\n") ;
-
-            m_Cmd << _T("info frame\n") << _T("end");
+                m_Cmd << _T("cbdisassemblyinitwitharg ") << m_hexAddrStr;
         };
 
         void ParseOutput(const wxString& p_output)
diff --git a/src/plugins/debuggergdb/gdb_driver.cpp b/src/plugins/debuggergdb/gdb_driver.cpp
index 79d22b0f..e77d36a4 100644
--- a/src/plugins/debuggergdb/gdb_driver.cpp
+++ b/src/plugins/debuggergdb/gdb_driver.cpp
@@ -142,6 +142,11 @@ void GDB_driver::Prepare(bool isConsole, int printElements)
 
     // debugger version
     QueueCommand(new DebuggerCmd(this, _T("show version")));
+
+    QueueCommand(new DebuggerCmd(this, _T("define cbdisassemblyinitwithpc\ndisassemble $pc,$pc+50\ninfo frame\nend\n")));
+
+    QueueCommand(new DebuggerCmd(this, _T("define cbdisassemblyinitwitharg\ndisassemble $arg0\ninfo frame\nend\n")));
+
     // no confirmation
     QueueCommand(new DebuggerCmd(this, _T("set confirm off")));
     // no wrapping lines

Note: if I don't add the "\n" in the end of the long new QueueCommand command string, I have the same issue as my original post, which means for GDB prompt to return, we need an extra "\n"?

So, for our old way, we only need an ending "\n" char? I haven't tested yet.
Code: [Select]
if 1
disassemble 0x00401650
info frame
end
« Last Edit: January 13, 2019, 05:38:19 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.