Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => Topic started by: ollydbg on April 05, 2012, 05:06:44 am

Title: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 05, 2012, 05:06:44 am
Code
void GDB_driver::ParseOutput(const wxString& output)
{
    m_Cursor.changed = false;

    // Watch for initial debug info and grab the child PID
    // this is put here because we need this info even if
    // we don't get a prompt back.
    // It's "cheap" anyway because the line we 're after is
    // the very first line printed by gdb when running our
    // program. It then sets the child PID and never enters here
    // again because the "want_debug_events" condition below
    // is not satisfied anymore...
    if (platform::windows && want_debug_events)
    {
        wxRegEx* re = 0;
        if ((m_GDBVersionMajor > 6 || (m_GDBVersionMajor == 6 && m_GDBVersionMinor >= 7)) &&
            output.Contains(_T("CREATE_PROCESS_DEBUG_EVENT")))
        {
            re = &reChildPid2;
        }
        else if (m_GDBVersionMajor <= 6 && output.Contains(_T("do_initial_child_stuff")))
            re = &reChildPid;
        else if (m_attachedToProcess)
            re = &reAttachedChildPid;

        if (re)
        {
            // got the line with the PID, parse it out:
            // e.g.
            // gdb: do_initial_child_stuff: process 1392
            if (re->Matches(output))
            {
                wxString pidStr = re->GetMatch(output, 1);
                long pid = 0;
                pidStr.ToLong(&pid);
                SetChildPID(pid);
                want_debug_events = false;
                disable_debug_events = true;
                m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
            }
        }
    }
    else if (!platform::windows && m_ChildPID == 0)
    {
        if (reChildPid3.Matches(output)) // [Switching to Thread -1234655568 (LWP 18590)]
        {
            wxString pidStr = reChildPid3.GetMatch(output, 1);
            long pid = 0;
            pidStr.ToLong(&pid);
            SetChildPID(pid);
            m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
        }
    }

    if (!want_debug_events &&
        (output.StartsWith(_T("gdb: ")) ||
        output.StartsWith(_T("Warning: ")) ||
        output.StartsWith(_T("ContinueDebugEvent "))))
    {
        return;
    }

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

    m_pDBG->DebugLog(output);

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

    if (disable_debug_events)
    {
        // we don't want debug events anymore (we got the pid)
        QueueCommand(new DebuggerCmd(this, _T("set debugevents off")));
        disable_debug_events = false;
    }

Here is the code to parse gdb output.
To catch the PID, we have different methods:
Under Windows, we need first "set debugevents on", and if we receive some message matches "CREATE_PROCESS_DEBUG_EVENT", then we get the PID, and send: "set debugevents off".

Under Linux, it is quite simple, just matches the message "[Switching to Thread -1234655568 (LWP 18590)]"

When I debug under Windows gdb, I see some message:

Code
Debugger name and version: GNU gdb (GDB) 7.4.50.20120331-cvs

[debug]>>>>>>cb_gdb:
[debug]> set width 0
[debug]>>>>>>cb_gdb:
[debug]> set height 0
[debug]>>>>>>cb_gdb:
[debug]> set breakpoint pending on
[debug]>>>>>>cb_gdb:
[debug]> set print asm-demangle on
[debug]>>>>>>cb_gdb:
[debug]> set unwindonsignal on
[debug]>>>>>>cb_gdb:
[debug]> set print elements 0
[debug]>>>>>>cb_gdb:
[debug]> set debugevents on
[debug]>>>>>>cb_gdb:
[debug]> set disassembly-flavor att
[debug]>>>>>>cb_gdb:
[debug]> catch throw
[debug]Catchpoint 1 (throw)
[debug]>>>>>>cb_gdb:
[debug]> source E:\code\gcc\PCXMinGW463\\bin\my.gdb
[debug]>>>>>>cb_gdb:
[debug]> directory E:/code/cb/test_code/IsAlpha/
[debug]Source directories searched: E:/code/cb/test_code/IsAlpha;$cdir;$cwd
[debug]>>>>>>cb_gdb:
[debug]> break "E:/code/cb/test_code/IsAlpha/IsAlphaMain.cpp:114"
[debug]Breakpoint 2 at 0x401f5c: file E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp, line 114.
[debug]>>>>>>cb_gdb:
[debug]> break "E:/code/cb/test_code/IsAlpha/IsAlphaMain.cpp:106"
[debug]Breakpoint 3 at 0x401e6b: file E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp, line 106.
[debug]>>>>>>cb_gdb:
[debug]> run
[debug]Starting program: E:\code\cb\test_code\IsAlpha\bin\Debug\IsAlpha.exe
[debug]gdb: windows_init_thread_list

Child process PID: 2684

[debug][New Thread 2684.0xf40]
[debug]Breakpoint 3, IsAlphaFrame::OnAbout (this=0xb66da0, event=...) at E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp:106
[debug]E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp:106:3032:beg:0x401e6b
[debug]>>>>>>cb_gdb:

At E:\code\cb\test_code\IsAlpha\IsAlphaMain.cpp:106

[debug]> set debugevents off
[debug]>>>>>>cb_gdb:

There are two point:
1, the set debugevents off command is send only after the first bp meet.
2, there are some message "[New Thread 2684.0xf40]", and this 2684 is just the PID, so can we simplify use this info to get PID?
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: MortenMacFly on April 05, 2012, 06:32:43 am
2, there are some message "[New Thread 2684.0xf40]", and this 2684 is just the PID, so can we simplify use this info to get PID?
If this also works with older, but wide spread debuggers (6.8) and also in other cases like attaching to a process for example - why not?
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 05, 2012, 06:48:42 am
2, there are some message "[New Thread 2684.0xf40]", and this 2684 is just the PID, so can we simplify use this info to get PID?
If this also works with older, but wide spread debuggers ( 6.8 ) and also in other cases like attaching to a process for example - why not?
I will test 6.8 version and give feedback.

I have never use "attaching a process" in c::b debugger plugin. But for this feature (I see it under "Debug" menu), we need to manually enter a PID number.



Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 05, 2012, 07:07:32 am
Ok, I just download this one:
gdb-6.8-mingw-3.tar.bz2 (http://sourceforge.net/projects/mingw/files/MinGW/Extension/gdb/Release%20Candidate_%20GDB%206.8-3/gdb-6.8-mingw-3.tar.bz2/download)

And it do have the same log:

Code
[debug]gdb: win32_init_thread_list

Child process PID: 1748

[debug][New thread 1748.0x1300]
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: Jenna on April 05, 2012, 07:24:02 am
Did you also test it with non-threaded application (simple hello world example should do it) ?
I don't get any such message here on linux in this case.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on April 05, 2012, 08:18:53 am
If it was that simple it would have been so easy, but this output is meant for people not IDEs, so it is random and not consistent.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 05, 2012, 12:49:14 pm
Did you also test it with non-threaded application (simple hello world example should do it) ?
My original test was a wxWidgets app(single thread), now I test a single thread hello world console app, both of them show the correct message that I needed.

Quote
I don't get any such message here on linux in this case.
If you look at the original post's code snippet, you can see
Code
    else if (!platform::windows && m_ChildPID == 0)
    {
        if (reChildPid3.Matches(output)) // [Switching to Thread -1234655568 (LWP 18590)]
        {
            wxString pidStr = reChildPid3.GetMatch(output, 1);
            long pid = 0;
            pidStr.ToLong(&pid);
            SetChildPID(pid);
            m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
        }
    }
This means, under Linux, it use reChildPid3, which is defined as:
Code
// [Switching to Thread -1234655568 (LWP 18590)]
// [New Thread -1234655568 (LWP 18590)]
static wxRegEx reChildPid3(_T("Thread[ \t]+[xA-Fa-f0-9-]+[ \t]+\\(LWP ([0-9]+)\\)]"));

So, as a conclusion, under Linux we don't need some kind of tricks (set on debugevents and later set off debugevents).

@obf:
I tested under Windows, both gdb 6.8 and gdb 7.4 show the PID correctly under the message pattern like:
Code
[New thread 1748.0x1300]
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on April 05, 2012, 12:52:50 pm
ollydbg: Patches welcome, but please wait for 2-3 days until we do the merge...

And Jens is correct because gdb doesn't always print the threading notifications, but if it works on windows I have nothing against it.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 05, 2012, 01:42:55 pm
ollydbg: Patches welcome, but please wait for 2-3 days until we do the merge...

And Jens is correct because gdb doesn't always print the threading notifications, but if it works on windows I have nothing against it.
Ok, I put this in my TODO list. Also, the patch should be only touch the Windows side (not Linux side).
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 10, 2012, 03:24:29 am
Code
Index: gdb_driver.cpp
===================================================================
--- gdb_driver.cpp (revision 7929)
+++ gdb_driver.cpp (working copy)
@@ -75,6 +75,7 @@
 // [Switching to Thread -1234655568 (LWP 18590)]
 // [New Thread -1234655568 (LWP 18590)]
 static wxRegEx reChildPid3(_T("Thread[ \t]+[xA-Fa-f0-9-]+[ \t]+\\(LWP ([0-9]+)\\)]"));
+static wxRegEx reChildPid4(_T("\\[New [tT]hread[ \t]+[0-9]+\\.[xA-Fa-f0-9-]+\\]"));
 static wxRegEx reAttachedChildPid(wxT("Attaching to process ([0-9]+)"));
 
 static wxRegEx reInferiorExited(wxT("^\\[Inferior[ \\t].+[ \\t]exited normally\\]$"), wxRE_EXTENDED);
@@ -92,8 +93,6 @@
     m_IsStarted(false),
     m_GDBVersionMajor(0),
     m_GDBVersionMinor(0),
-    want_debug_events(true),
-    disable_debug_events(false),
     m_attachedToProcess(false),
     m_catchThrowIndex(-1)
 {
@@ -243,19 +242,6 @@
     // disalbe result string truncations
     QueueCommand(new DebuggerCmd(this, wxString::Format(wxT("set print elements %d"), printElements)));
 
-    // want debug events
-    if(platform::windows)
-    {
-        QueueCommand(new DebuggerCmd(this, _T("set debugevents on")));
-        want_debug_events = true;
-        disable_debug_events = false;
-    }
-    else
-    {
-        want_debug_events = false;
-        disable_debug_events = false;
-    }
-
     if (platform::windows && isConsole)
         QueueCommand(new DebuggerCmd(this, _T("set new-console on")));
 
@@ -750,43 +736,18 @@
 {
     m_Cursor.changed = false;
 
-    // Watch for initial debug info and grab the child PID
-    // this is put here because we need this info even if
-    // we don't get a prompt back.
-    // It's "cheap" anyway because the line we 're after is
-    // the very first line printed by gdb when running our
-    // program. It then sets the child PID and never enters here
-    // again because the "want_debug_events" condition below
-    // is not satisfied anymore...
-    if (platform::windows && want_debug_events)
+    if (platform::windows && m_ChildPID == 0)
     {
-        wxRegEx* re = 0;
-        if ((m_GDBVersionMajor > 6 || (m_GDBVersionMajor == 6 && m_GDBVersionMinor >= 7)) &&
-            output.Contains(_T("CREATE_PROCESS_DEBUG_EVENT")))
+        if (reChildPid4.Matches(output)) // [New Thread 2684.0xf40] or [New thread 2684.0xf40]
         {
-            re = &reChildPid2;
+            wxString pidStr = reChildPid4.GetMatch(output, 0);
+            pidStr = pidStr.BeforeFirst(_T('.')); //[New Thread 2684.0xf40] -> [New Thread 2684
+            pidStr = pidStr.AfterFirst(_T('d')); //[New Thread 2684 ->  2684
+            long pid = 0;
+            pidStr.ToLong(&pid);
+            SetChildPID(pid);
+            m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
         }
-        else if (m_GDBVersionMajor <= 6 && output.Contains(_T("do_initial_child_stuff")))
-            re = &reChildPid;
-        else if (m_attachedToProcess)
-            re = &reAttachedChildPid;
-
-        if (re)
-        {
-            // got the line with the PID, parse it out:
-            // e.g.
-            // gdb: do_initial_child_stuff: process 1392
-            if (re->Matches(output))
-            {
-                wxString pidStr = re->GetMatch(output, 1);
-                long pid = 0;
-                pidStr.ToLong(&pid);
-                SetChildPID(pid);
-                want_debug_events = false;
-                disable_debug_events = true;
-                m_pDBG->Log(wxString::Format(_("Child process PID: %d"), pid));
-            }
-        }
     }
     else if (!platform::windows && m_ChildPID == 0)
     {
@@ -800,10 +761,9 @@
         }
     }
 
-    if (!want_debug_events &&
-        (output.StartsWith(_T("gdb: ")) ||
-        output.StartsWith(_T("Warning: ")) ||
-        output.StartsWith(_T("ContinueDebugEvent "))))
+    if (  output.StartsWith(_T("gdb: "))
+        ||output.StartsWith(_T("Warning: "))
+        ||output.StartsWith(_T("ContinueDebugEvent ")))
     {
         return;
     }
@@ -822,13 +782,6 @@
         return; // come back later
     }
 
-    if (disable_debug_events)
-    {
-        // we don't want debug events anymore (we got the pid)
-        QueueCommand(new DebuggerCmd(this, _T("set debugevents off")));
-        disable_debug_events = false;
-    }
-
     m_QueueBusy = false;
     int changeFrameAddr = 0 ;
     DebuggerCmd* cmd = CurrentCommand();
Index: gdb_driver.h
===================================================================
--- gdb_driver.h (revision 7929)
+++ gdb_driver.h (working copy)
@@ -127,8 +127,6 @@
         long m_GDBVersionMinor;
         wxString flavour;
 
-        bool want_debug_events;
-        bool disable_debug_events;
         bool m_attachedToProcess;
 
         // for remote debugging usage (mainly)

This patch works OK under MinGW GDB6.8 and GDB7.4.

Comments are welcome.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on April 10, 2012, 07:56:55 am
You're very bold in removing the debug events code.
Are you really really sure that gdb will print these messages for every program you start?
What about remote debugging, can you try it?
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 10, 2012, 08:24:07 am
You're very bold in removing the debug events code.
:)

Quote
Are you really really sure that gdb will print these messages for every program you start?
I'm sure at least Windows GDB 6.8-7.4.


Quote
What about remote debugging, can you try it?
I have never used remote debugging. I will try it under WinXP.

BTW:
The debug event on/off feature is a windows only feature implemented in GDB's source file:
Code
gdb\windows-nat.c

It have such code snippet:
Code
#define DEBUG_EVENTS(x)	if (debug_events)	printf_unfiltered x

and: Windows debug event handling.
Code
    case CREATE_PROCESS_DEBUG_EVENT:
      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
    (unsigned) current_event.dwProcessId,
    (unsigned) current_event.dwThreadId,
    "CREATE_PROCESS_DEBUG_EVENT"));
      CloseHandle (current_event.u.CreateProcessInfo.hFile);
      if (++saw_create != 1)
break;
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 10, 2012, 09:34:40 am
@OBF:
I have finally find that how the
Code
[New Thread 2684.0xf40]
Message come from under Windows.

In GDB top level, there is a function in: "gdb\thread.c"
Code
struct thread_info *
add_thread_with_info (ptid_t ptid, struct private_thread_info *private)
{
  struct thread_info *result = add_thread_silent (ptid);

  result->private = private;

  if (print_thread_events)
    printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));

  annotate_new_thread ();
  return result;
}


The function target_pid_to_str() has different implementation in different target, under Windows, it lowers down to "gdb\windows-nat.c"

Code
/* Convert pid to printable format.  */
static char *
windows_pid_to_str (struct target_ops *ops, ptid_t ptid)
{
  static char buf[80];

  if (ptid_get_tid (ptid) != 0)
    {
      snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
ptid_get_pid (ptid), ptid_get_tid (ptid));
      return buf;
    }

  return normal_pid_to_str (ptid);
}
You see, the "Thread %d.0x%lx", the ptid_get_pid (ptid) value is just the PID.

BTW:
In gdb/thread.c
Code
/* Print notices when new threads are attached and detached.  */
int print_thread_events = 1;
static void
show_print_thread_events (struct ui_file *file, int from_tty,
                          struct cmd_list_element *c, const char *value)
{
  fprintf_filtered (file,
    _("Printing of thread events is %s.\n"),
                    value);
}

This means: the value print_thread_events is enabled by default. That's why we get such message under both Windows and Linux.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on April 10, 2012, 10:20:20 am
This means: the value print_thread_events is enabled by default. That's why we get such message under both Windows and Linux.
This is not 100% true for Linux and some (if not all) versions of gdb-7.xx, if you program doesn't use pthreads, it doesn't print it.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 10, 2012, 03:49:08 pm
This means: the value print_thread_events is enabled by default. That's why we get such message under both Windows and Linux.
This is not 100% true for Linux and some (if not all) versions of gdb-7.xx, if you program doesn't use pthreads, it doesn't print it.
Ok, I'm not quite familiar with Linux, so I may wrong.

I have just did under Windows (gdb.exe, this is the local side and gdbserver.exe, this is the remote target side)

See the log on gdbserver side (remote side)
Code
E:\code\gdb\gdbservertest>gdbserver localhost:777 IsAlphaConsole.exe
Process IsAlphaConsole.exe created; pid = 1804
Listening on port 777
Remote debugging from host 127.0.0.1
48 is a digit
49 is a digit
50 is a digit
51 is a digit
52 is a digit
53 is a digit
54 is a digit
55 is a digit
56 is a digit
57 is a digit
178 is a digit
179 is a digit
185 is a digit

GDB side: (local side)
Code
E:\code\gdb\gdbbin>gdb IsAlphaConsole.exe
GNU gdb (GDB) 7.4.50.20120331-cvs
Copyright (C) 2012 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".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from E:\code\gdb\gdbbin\IsAlphaConsole.exe...done.
(gdb) target remote localhost:777
Remote debugging using localhost:777
0x7c90120f in ntdll!DbgUiConnectToDbg () from C:\WINDOWS\system32\ntdll.dll
(gdb) b main
Breakpoint 1 at 0x4016ee: file E:\code\cb\test_code\IsAlphaConsole\main.cpp, lin
e 10.
(gdb) b main.cpp:15
Breakpoint 2 at 0x401753: file E:\code\cb\test_code\IsAlphaConsole\main.cpp, lin
e 15.
(gdb) continue
Continuing.

Breakpoint 1, main () at E:\code\cb\test_code\IsAlphaConsole\main.cpp:10
10          for (i = 0; i < 500; ++i)
(gdb) c
Continuing.

Breakpoint 2, main () at E:\code\cb\test_code\IsAlphaConsole\main.cpp:16
16          for (i = 0; i < 500; ++i)
(gdb)

I'm not sure how Codeblocks catch the PID in the remote side?
It seems that the only interested line is:
Code
Process IsAlphaConsole.exe created; pid = 1804
This is the PID in the remote target. So, my patch does not touch the remote debugging feature in c::b.
See the log when I enable debugevent on in gdb.exe side:
Code
E:\code\gdb\gdbbin>gdb IsAlphaConsole.exe
GNU gdb (GDB) 7.4.50.20120331-cvs
Copyright (C) 2012 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".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from E:\code\gdb\gdbbin\IsAlphaConsole.exe...done.
(gdb) set debugevents on
(gdb) target remote localhost:777
Remote debugging using localhost:777
0x7c90120f in ntdll!DbgUiConnectToDbg () from C:\WINDOWS\system32\ntdll.dll
(gdb) b main
Breakpoint 1 at 0x4016ee: file E:\code\cb\test_code\IsAlphaConsole\main.cpp, lin
e 10.
(gdb) b main.cpp:15
Breakpoint 2 at 0x401753: file E:\code\cb\test_code\IsAlphaConsole\main.cpp, lin
e 15.
(gdb) c
Continuing.

Breakpoint 1, main () at E:\code\cb\test_code\IsAlphaConsole\main.cpp:10
10          for (i = 0; i < 500; ++i)
(gdb) c
Continuing.

So, As a conclusion: no PID information about the process in remote side is shown here if I enable debugevents on.




Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on April 10, 2012, 04:16:39 pm
Uff, sorry, the PID is not needed in remote debugging, because in this case gdb expects ctrl-c events for stopping it.

Morten: Can you do some testing of this patch? If I remember correctly you had some debugevent related problems, so this could be your fix. :)
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: MortenMacFly on April 10, 2012, 05:33:15 pm
Morten: Can you do some testing of this patch? If I remember correctly you had some debugevent related problems, so this could be your fix. :)
...which patch? The one applied in trunk already?
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on April 10, 2012, 05:39:05 pm
This one, I think: http://forums.codeblocks.org/index.php/topic,16159.msg109312.html#msg109312

ollydbg: Is there a chance to try your patch in a 64bit windows with a 64bit executable?
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 11, 2012, 01:50:08 am
ollydbg: Is there a chance to try your patch in a 64bit windows with a 64bit executable?
Sorry, I do not have a 64bit Windows system nor a 64bit gdb.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: ollydbg on April 20, 2012, 03:25:48 am
Commit this in rev7936.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: Huki on January 29, 2016, 06:43:44 pm
I'm on linux with GDB 7.10, and CB never gets the correct pid for me. This means I can't pause or set any breakpoints after I start debugging. Here's some log:

Quote
[...]
[debug]>>>>>>cb_gdb:
[debug]> run
[debug]Starting program: /home/gokul/Documents/Projects/CodeBlocks/src/devel/codeblocks --debug-log --multiple-instance -ns -ni -v -p debug
[debug][Thread debugging using libthread_db enabled]
[debug]Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".

Child process PID: 14736

[debug][New Thread 0xb5565b40 (LWP 14736)]

[debug][New Thread 0xb4d64b40 (LWP 14737)]
[debug][New Thread 0xb4563b40 (LWP 14738)]
[debug][New Thread 0xb3b0db40 (LWP 14739)]
[debug][New Thread 0xb330cb40 (LWP 14740)]
[debug][New Thread 0xb1966b40 (LWP 14747)]
[debug][New Thread 0xb0fcdb40 (LWP 14801)]
[debug][New Thread 0xb076db40 (LWP 14802)]
[debug][New Thread 0xafec0b40 (LWP 14803)]
[debug][Thread 0xafec0b40 (LWP 14803) exited]
[debug][Thread 0xb0fcdb40 (LWP 14801) exited]
[debug][Thread 0xb076db40 (LWP 14802) exited]
[debug][Thread 0xb1966b40 (LWP 14747) exited]
[debug]Starting Code::Blocks svn build  rev 10703 Jan 29 2016, 03:07:41 - wx2.8.12 (Linux, unicode) - 32 bit
[debug][Thread 0xb4563b40 (LWP 14738) exited]
[debug][Thread 0xb4d64b40 (LWP 14737) exited]
[debug][Thread 0xb5565b40 (LWP 14736) exited]
[debug][Thread 0xb330cb40 (LWP 14740) exited]
[debug][Thread 0xb3b0db40 (LWP 14739) exited]
[debug][Inferior 1 (process 14101) exited normally]
[debug]>>>>>>cb_gdb:

[Inferior 1 (process 14101) exited normally]

[debug]> quit

Debugger finished with status 0

You can see CB tries to get the pid by parsing the thread info, i.e., the line in red:
"[New Thread 0xb5565b40 (LWP 14736)]"
but this is not the correct pid of the inferior process! The correct pid can be seen at the end, in the green line:
"[Inferior 1 (process 14101) exited normally]"

The only proper way to get the pid seems to be to start gdb in "break on entry" mode and run "info program" or "info inferior" at the gdb prompt, parse the result and then continue. I see there is already support for "info program", so why not use that? I'll post a patch in a while...

Edit: Here's the patch which works for me:
Code: diff
From 9f668e2611366fde9e9ee3a8bd17f553bafd30fb Mon Sep 17 00:00:00 2001
From: huki <gk7huki@gmail.com>
Date: Sat, 30 Jan 2016 02:51:50 +0530
Subject: [PATCH] debugger_gdb: [huki] properly get the pid of the inferior
 process

We now break on entry and extract the pid through "info program", then continue if needed.
Fixed functionality of m_ManualBreakOnEntry.
Keep old way of catching pid for remoteDebugging.
---
 src/plugins/debuggergdb/gdb_commands.h |  3 +++
 src/plugins/debuggergdb/gdb_driver.cpp | 10 ++++++++++
 2 files changed, 13 insertions(+)

diff --git a/src/plugins/debuggergdb/gdb_commands.h b/src/plugins/debuggergdb/gdb_commands.h
index 3021cd7..5536c84 100644
--- a/src/plugins/debuggergdb/gdb_commands.h
+++ b/src/plugins/debuggergdb/gdb_commands.h
@@ -722,7 +722,10 @@ class GdbCmd_InfoProgram : public DebuggerCmd
             {
                 long pid;
                 if (pid_str.ToLong(&pid, 10) && pid != 0)
+                {
                     m_pDriver->SetChildPID(pid);
+                    m_pDriver->GetDebugger()->Log(wxString::Format(_("Child process PID: %ld"), pid));
+                }
             }
         }
 };
diff --git a/src/plugins/debuggergdb/gdb_driver.cpp b/src/plugins/debuggergdb/gdb_driver.cpp
index cc1ccd5..b2365c9 100644
--- a/src/plugins/debuggergdb/gdb_driver.cpp
+++ b/src/plugins/debuggergdb/gdb_driver.cpp
@@ -503,6 +503,7 @@ void GDB_driver::Start(bool breakOnEntry)
     {
         m_ManualBreakOnEntry = !remoteDebugging;
         // start the process
+        #if 0
         if (breakOnEntry)
             QueueCommand(new GdbCmd_Start(this, remoteDebugging ? _T("continue") : _T("start")));
         else
@@ -511,6 +512,9 @@ void GDB_driver::Start(bool breakOnEntry)
             m_ManualBreakOnEntry=false;  // must be reset or gdb does not stop at first breakpoint
             QueueCommand(new GdbCmd_Start(this, remoteDebugging ? _T("continue") : _T("run")));
         }
+        #endif
+        // NOTE(huki): use "start" command so we can break on entry and run "info program" to get the pid
+        QueueCommand(new GdbCmd_Start(this, remoteDebugging ? _T("continue") : _T("start")));
         m_IsStarted = true;
     }
 } // Start
@@ -778,6 +782,7 @@ void GDB_driver::ParseOutput(const wxString& output)
 {
     m_Cursor.changed = false;
 
+    // NOTE(huki): this doesn't work on linux with GDB 7 - the pid given in the output is wrong
     if (platform::windows && m_ChildPID == 0)
     {
         if (reChildPid2.Matches(output)) // [New Thread 2684.0xf40] or [New thread 2684.0xf40]
@@ -1043,6 +1048,7 @@ void GDB_driver::ParseOutput(const wxString& output)
                     m_needsUpdate = true;
                 }
             }
+            m_ManualBreakOnEntry = false;   // must be reset or gdb does not stop at first breakpoint
         }
 
         else if (lines[i].StartsWith(wxT("Temporary breakpoint")))
@@ -1177,7 +1183,11 @@ void GDB_driver::HandleMainBreakPoint(const wxRegEx& reBreak_in, wxString line)
             QueueCommand(new GdbCmd_InfoProgram(this), DebuggerDriver::High);
 
         if (m_ManualBreakOnEntry && !m_BreakOnEntry)
+        {
+            m_ManualBreakOnEntry = false;
+            m_ProgramIsStopped = true;
             Continue();
+        }
         else
         {
             m_ManualBreakOnEntry = false;
--
2.5.0


Edit2: Updated the patch with few fixes, also keeps the old way of catching pid as a fallback (eg, for remote debugging).
commit on git (https://github.com/gk7huki/codeblocks_sf/commit/9f668e2611366fde9e9ee3a8bd17f553bafd30fb)
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on January 30, 2016, 12:15:36 am
Don't like this patch. I've not looked at the whole of it, just saw the part with the mandatory break-on-entry.
And I don't like it, because it sounds too fragile. I have a patch that uses the system apis to find the pids.
Can you try it? Probably you should disable the pid detection.

Code: diff
From b7a560ac02d6e0f2bedab5a6f02b0fd14875be19 Mon Sep 17 00:00:00 2001
From: T Petrov <tpetrov@codeblocks.org>
Date: Sat, 30 Jan 2016 01:13:12 +0200
Subject: [PATCH] * debugger: Find the debuggee's PID using OS APIs when the
 parsing the log fails

---
 src/include/globals.h                   |  6 ++
 src/plugins/debuggergdb/debuggergdb.cpp | 15 ++++-
 src/sdk/globals.cpp                     | 98 +++++++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+), 1 deletion(-)

diff --git a/src/include/globals.h b/src/include/globals.h
index 704924d..b84aafb 100644
--- a/src/include/globals.h
+++ b/src/include/globals.h
@@ -386,4 +386,10 @@ namespace platform
 // one thing that's not checked yet are circular symlinks - watch out!
 extern DLLIMPORT wxString realpath(const wxString& path);

+/** Return a vector full with the PIDs of the child processes of the parent.
+  * @param[out] children List of PIDs of the child processes of the parent
+  * @param[in] parent PID of the parent process
+  */
+extern DLLIMPORT void cbGetChildrenPIDs(std::vector<int> &children, int parent);
+
 #endif // SDK_GLOBALS_H
diff --git a/src/plugins/debuggergdb/debuggergdb.cpp b/src/plugins/debuggergdb/debuggergdb.cpp
index fded9a9..888de11 100644
--- a/src/plugins/debuggergdb/debuggergdb.cpp
+++ b/src/plugins/debuggergdb/debuggergdb.cpp
@@ -1583,7 +1583,20 @@ void DebuggerGDB::DoBreak(bool temporary)
             pid = 0;
         }
         if (pid <= 0)
-            pid = m_Pid; // try poking gdb directly
+        {
+            DebugLog(_("Child PID have not been detected!"), Logger::warning);
+            std::vector<int> childrenPIDs;
+            cbGetChildrenPIDs(childrenPIDs, m_Pid);
+            if (!childrenPIDs.empty())
+            {
+                if (childrenPIDs.size()>1)
+                    DebugLog(_("Found more than one child processes. Use the PID of the first "), Logger::warning);
+                pid = childrenPIDs.front();
+                m_State.GetDriver()->SetChildPID(pid);
+            }
+            else
+                pid = m_Pid; // try poking gdb directly
+        }
         // non-windows gdb can interrupt the running process. yay!
         if (pid <= 0) // look out for the "fake" PIDs (killall)
             cbMessageBox(_("Unable to stop the debug process!"), _("Error"), wxOK | wxICON_WARNING);
diff --git a/src/sdk/globals.cpp b/src/sdk/globals.cpp
index d44d81d..b2b3e52 100644
--- a/src/sdk/globals.cpp
+++ b/src/sdk/globals.cpp
@@ -1453,3 +1453,101 @@ int cbProjectTreeImages::VirtualFolderIconIndex()
 {
     return (int)fvsVirtualFolder;
 }
+
+namespace
+{
+static int ParseParentPID(const char *line)
+{
+    const char *p = strchr(line, '(');
+    if (!p)
+        return -1;
+    ++p;
+    int open_paren_count = 1;
+    while (*p && open_paren_count > 0)
+    {
+        switch (*p)
+        {
+        case '(':
+            open_paren_count++;
+            break;
+        case ')':
+            open_paren_count--;
+            break;
+        }
+
+        ++p;
+    }
+    if (*p == ' ')
+        ++p;
+    int dummy;
+    int ppid;
+    int count = sscanf(p, "%c %d", (char *) &dummy, &ppid);
+    return count == 2 ? ppid : -1;
+}
+
+} // namespace
+
+void cbGetChildrenPIDs(std::vector<int> &children, int parent)
+{
+#ifndef __WXMSW__
+    const char *c_proc_base = "/proc";
+    DIR *dir = opendir(c_proc_base);
+    if (!dir)
+        return;
+    struct dirent *entry;
+    do
+    {
+        entry = readdir(dir);
+        if (entry)
+        {
+            int pid = atoi(entry->d_name);
+            if (pid != 0)
+            {
+                char filestr[PATH_MAX + 1];
+                snprintf(filestr, PATH_MAX, "%s/%d/stat", c_proc_base, pid);
+                FILE *file = fopen(filestr, "r");
+                if (file)
+                {
+                    char line[101];
+                    fgets(line, 100, file);
+                    fclose(file);
+                    int ppid = ParseParentPID(line);
+                    if (ppid == parent)
+                        children.push_back(pid);
+                }
+            }
+        }
+    } while (entry);
+    closedir(dir);
+#else
+    // get a function pointer to DebugBreakProcess under windows (XP+)
+    typedef HANDLE WINAPI (*CreateToolhelp32SnapshotApiCall)(DWORD dwFlags, DWORD th32ProcessID);
+    static CreateToolhelp32SnapshotApiCall CreateToolhelp32SnapshotFunc = 0;
+    #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
+    if (!CreateToolhelp32SnapshotFunc) {
+        kernelLib = LoadLibrary(TEXT("kernel32.dll"));
+        if (kernelLib)
+            CreateToolhelp32SnapshotFunc = (CreateToolhelp32SnapshotApiCall)GetProcAddress(kernelLib, "CreateToolhelp32Snapshot");
+    }
+    #endif
+
+    if ((CreateToolhelp32SnapshotFunc!=NULL) && (Process32FirstFunc!=NULL) && (Process32NextFunc!=NULL) )
+    {
+        HANDLE snap = CreateToolhelp32SnapshotFunc(TH32CS_SNAPALL,0);
+        if (snap!=INVALID_HANDLE_VALUE)
+        {
+            PROCESSENTRY32 lppe;
+            lppe.dwSize = sizeof(PROCESSENTRY32);
+            BOOL ok = Process32FirstFunc(snap, &lppe);
+            while (ok == TRUE)
+            {
+                if (lppe.th32ParentProcessID == parent) // Have my Child...
+                    children.push_back(lppe.th32ProcessID);
+                lppe.dwSize = sizeof(PROCESSENTRY32);
+                ok = Process32NextFunc(snap, &lppe);
+            }
+            CloseHandle(snap);
+        }
+    }
+#endif
+}
--
2.7.0

p.s. This is not the final version of the patch, but it should be good enough to test if the concept is working.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: Huki on January 30, 2016, 04:56:37 pm
Ok, I reverted my patch and tried yours: it's working for me. Part of the log:
Quote
Child process PID: 8295

[debug][New Thread 0xb4b27b40 (LWP 8295)]
[debug][New Thread 0xb4b27b40 (LWP 8296)]
[debug][Thread 0xb4b27b40 (LWP 8295) exited]
[debug][New Thread 0xb01ffb40 (LWP 8297)]
[debug]Child process (pid:8295) doesn't exists
[debug]Child PID have not been detected!

Trying to interrupt process with pid: 8290; child pid: 8295 gdb pid: 8288
Continuing...

[debug]Program received signal SIGINT, Interrupt.
[debug]0xb7fdbbe8 in __kernel_vsyscall ()
[debug]>>>>>>cb_gdb:

Btw, your pid detection is triggered only if the wxProcess::Exist() with the old pid fails. I noticed it sometimes does not fail.. ie, I know the pid doesn't exist (there is no such pid in system monitor), but wxProcess::Exist() is still successful. On some other projects it always fails with the old pid, but it's not reliable. So it's probably better to disable the old pid catching (at least on linux).
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on January 30, 2016, 07:05:38 pm
I'm fine disabling the pid detection from the log.
In general it needs a threaded program in order to find something, because it looks for the "new thread" messages.
For some reason on your systems the first thread doesn't have the same pid as the process.

Can you check if the parent pid of the threads in your program is the same as the pid of the process?
We can use the old_pid to find the parent pid, but for this to be reliable we'll need to start parsing the "thread exited" messages.
And we should keep a list with all alive threads in the application. This sounds complex and a bit unreliable.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: MortenMacFly on January 30, 2016, 09:55:17 pm
Can you try it? Probably you should disable the pid detection.
Does not compile at all on Windows. Process32FirstFunc and Process32NextFunc are undefined. Did you miss to provide some portions?
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: MortenMacFly on January 30, 2016, 10:07:58 pm
Did you miss to provide some portions?
Maybe the Windows part should more look like this:
Code: cpp
    // get a function pointer to DebugBreakProcess under windows (XP+)
    typedef HANDLE WINAPI CreateToolhelp32SnapshotFunc(DWORD dwFlags, DWORD th32ProcessID);
    static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL;
    typedef BOOL WINAPI Process32FirstFunc(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
    static Process32FirstFunc* firstFunc = NULL;
    typedef BOOL WINAPI Process32NextFunc(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
    static Process32NextFunc* nextFunc = NULL;
    HMODULE kernel32DLL = LoadLibrary(TEXT("kernel32.dll"));
    if (kernel32DLL)
    {
        snapshotFunc = (CreateToolhelp32SnapshotFunc*) GetProcAddress(kernel32DLL, "CreateToolhelp32Snapshot");
        firstFunc    = (Process32FirstFunc*)           GetProcAddress(kernel32DLL, "Process32First");
        nextFunc     = (Process32NextFunc*)            GetProcAddress(kernel32DLL, "Process32Next");
    }
    if ( (NULL!=snapshotFunc) && (NULL!=firstFunc) && (NULL!=nextFunc) )
    {
        HANDLE snap = snapshotFunc(TH32CS_SNAPALL,0);
        if (snap!=INVALID_HANDLE_VALUE)
        {
            PROCESSENTRY32 lppe;
            lppe.dwSize = sizeof(PROCESSENTRY32);
            BOOL ok = firstFunc(snap, &lppe);
            while (ok == TRUE)
            {
                if (lppe.th32ParentProcessID == parent) // Have my Child...
                    children.push_back(lppe.th32ProcessID);
                lppe.dwSize = sizeof(PROCESSENTRY32);
                ok = nextFunc(snap, &lppe);
            }
            CloseHandle(snap);
        }
    }
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on January 30, 2016, 10:41:04 pm
I've not tested it on windows, yet.
And I think I have to turn it into a class that is owned by the debugger plugin, so it will be able to do the dll cleanup.

This is just a proof of concept if it solves the problem.
Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: Huki on January 31, 2016, 03:12:43 pm
For some reason on your systems the first thread doesn't have the same pid as the process.
In fact the main thread does have the same pid as the process, but it's not printed by gdb. Gdb only seems to print additionally created threads. As an example, this is a gdb log with thread info (note that there is no "New Thread" message for the main thread):
Code
[New Thread 0xb4b27b40 (LWP 3861)]
[Thread 0xb4b27b40 (LWP 3861) exited]
[New Thread 0xb4b27b40 (LWP 3862)]
[New Thread 0xb01feb40 (LWP 3863)]
^C
Program received signal SIGINT, Interrupt.
0xb7fdbbe8 in __kernel_vsyscall ()
(gdb) info threads
  Id   Target Id         Frame
  4    Thread 0xb01feb40 (LWP 3863) [...]
  3    Thread 0xb4b27b40 (LWP 3862) [...]
* 1    Thread 0xb5240780 (LWP 3857) [...]
(gdb) info program
Using the running image of child Thread 0xb5240780 (LWP 3857).

Quote
Can you check if the parent pid of the threads in your program is the same as the pid of the process?
Yes it is:
Code
~$ ps -L 3857
  PID   LWP TTY      STAT   TIME COMMAND
 3857  3857 pts/9    tl     0:00 [...]
 3857  3862 pts/9    tl     0:00 [...]
 3857  3863 pts/9    tl     0:00 [...]

Title: Re: debugger plugin: catch the inferior PID under gdb
Post by: oBFusCATed on January 31, 2016, 03:41:49 pm
Thanks. I'll make a proper patch that could be tested.