gdbembeddedremote-debuggingopenocd

Using GDB to load 2 programs, only connect the 2nd to the remote target after the completion of the first


I want to load 2 programs in the same GDB session using inferior, however I only want program 2 to run after the breakpoint event from program 1. When this event is reached, I want to connect my 2nd program so as not to disconnect GDB from the device causing a reset on the remote device. This task i want to be automated to enable running of many tests in a series of tests. This code is in my .sh script run on cygwin.

Here is a sample of the code i have been trying to run;

gdb -batch -l 20 \
  -ex "target extended-remote localhost:3333" \
  -ex "load ${progA}" \
  -ex "add-inferior -exec ${progB} -no-connection" \
  -ex "run" \
  -ex "inferior infno" \
  -ex "target extended-remote localhost:3333" \
  -ex "continue"

The result is the disconnection of GDB from the target causing a device reset when the connection is re-established. I also move past the breakpoint event.


Solution

  • The problem here is the use of inferior infno, this isn't a thing, there's no convenience variable or keyword that means switch to an inferior that is not otherwise running.

    However, you can create a convenience function in Python that does what you want. Add the following to a nri.py file:

    class next_runnable_inferior(gdb.Function):
      """Return the number of the next runnable inferior."""
    
      def __init__(self):
          super ().__init__("next_runnable_inferior")
    
      def invoke(self):
        for inf in gdb.inferiors():
          if len(inf.threads()) == 0:
            return inf.num
        raise gdb.GdbError("All inferiors are running")
    
    next_runnable_inferior()
    

    Then inside a GDB session:

    (gdb) source /tmp/nri.py
    (gdb) inferior $next_runnable_inferior()
    [Switching to inferior 1 [<null>] (<noexec>)]
    (gdb) add-inferior
    [New inferior 2]
    Added inferior 2
    (gdb) inferior $next_runnable_inferior()
    [Switching to inferior 1 [<null>] (<noexec>)]
    (gdb) file /tmp/hello.x
    Reading symbols from /tmp/hello.x...
    (gdb) start
    Temporary breakpoint 1 at 0x401198: file /tmp/hello.c, line 18.
    Starting program: /tmp/hello.x
    
    Temporary breakpoint 1, main () at /tmp/hello.c:18
    18    printf ("Hello World\n");
    (gdb) inferior $next_runnable_inferior()
    [Switching to inferior 2 [<null>] (<noexec>)]
    (gdb) file /tmp/hello.x
    Reading symbols from /tmp/hello.x...
    (gdb) inferior $next_runnable_inferior()
    [Switching to inferior 2 [<null>] (/tmp/hello.x)]
    (gdb) start
    Temporary breakpoint 2 at 0x401198: -qualified main. (2 locations)
    Starting program: /tmp/hello.x
    
    Thread 2.1 "hello.x" hit Temporary breakpoint 2.2, main () at /tmp/hello.c:18
    18    printf ("Hello World\n");
    (gdb) inferior $next_runnable_inferior()
    All inferiors are running
    (gdb) inferior 1
    [Switching to inferior 1 [process 188577] (/tmp/hello.x)]
    [Switching to thread 1.1 (process 188577)]
    #0  main () at /tmp/hello.c:18
    18    printf ("Hello World\n");
    (gdb) kill
    Kill the program being debugged? (y or n) y
    [Inferior 1 (process 188577) killed]
    (gdb) inferior 2
    [Switching to inferior 2 [process 188613] (/tmp/hello.x)]
    [Switching to thread 2.1 (process 188613)]
    #0  main () at /tmp/hello.c:18
    18    printf ("Hello World\n");
    (gdb) inferior $next_runnable_inferior()
    [Switching to inferior 1 [<null>] (/tmp/hello.x)]
    (gdb)