2

I want to add a breakpoint in the line system("/path/to/world") in VS Code for debugging the /path/to/world program with gdb.

Here is the source code of /path/to/hello.c:

int main(int argc, char **argv)
{
    system("/path/to/world");
    return 0;
}

Here is the source code of /path/to/world.c:

int main(int argc, char **argv)
{
    printf("Hello World");
    return 0;
}

If using system() is not possible for debugging external program with a breakpoint in the main function, then what function or what method should be used instead?

How to debug external program in the main function in c with a breakpoint?

Update:

After adding a breakpoint in the line of "system("/path/to/world");" in VS Code and run the hello program in debug mode, after VS Code hits the line "system("/path/to/world");", and then I click the "Step Into" button, the following error will be shown:

Could not load source './stdlib/../sysdeps/posix/system.c': 'SourceRequest' not supported..
5
  • 6
    You don't. You debug it separately. Commented Oct 29 at 18:42
  • 1
    See sourceware.org/gdb/current/onlinedocs/gdb.html/Forks.html for how to tell gdb to debug a subprocess. Commented Oct 29 at 19:28
  • 1
    @dbush I'm not so sure. set fork-follow-mode child and set follow-exec-mode new should in theory follow the child process. But here's one older question documenting problems: stackoverflow.com/questions/10671229/… Commented Oct 29 at 19:32
  • Adding to dbush's comment: I assume that the code in the question is simplified. In this simple case there is no reason why you cannot simply debug /path/to/world without running hello. If you have more interaction between hello and world, describe this in your question. I wrote an answer based on a use case I had in the past. Commented Oct 30 at 9:24
  • The problem with "Step Into" is expected when you don't have the source code of the library function "system" available. "Step Into" means to execute the called function step-by-step, it is not related to the program world you want to run. Commented Oct 30 at 11:07

2 Answers 2

6

It is not clear from your question what you have tried, and what isn't working. Using your hello and world examples, here's my GDB session doing what I think you want to do:

$ gdb ./hello
GDB Version: 17.1

Reading symbols from ./hello...
(gdb) tbreak 5
Temporary breakpoint 1 at 0x401135: file hello.c, line 5.
(gdb) run
Starting program: /tmp/exec-test/hello

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffa3e8) at hello.c:5
5       system("/tmp/exec-test/world");
(gdb) set follow-fork-mode child
(gdb) break main if (strcmp (basename (argv[0]), "world") == 0)
Breakpoint 2 at 0x401135: file hello.c, line 5.
(gdb) continue
Continuing.
[Attaching after process 3719461 vfork to child process 3719507]
[New inferior 2 (process 3719507)]
[Detaching vfork parent process 3719461 after child exec]
[Inferior 1 (process 3719461) detached]
process 3719507 is executing new program: /usr/bin/bash
process 3719507 is executing new program: /tmp/exec-test/world

Thread 2.1 "world" hit Breakpoint 2, main (argc=1, argv=0x7fffffffa3f8) at world.c:5
5       printf("Hello World\n");
(gdb) info inferiors
  Num  Description       Connection           Executable
  1    <null>                                 /tmp/exec-test/world
* 2    process 3719507   1 (native)           /tmp/exec-test/world
(gdb)

I use set follow-fork-mode child so GDB will follow the child process in a fork rather than the parent. The execve calls will automatically be followed within the same inferior. I think the inferior 2 comes about due to the vfork() call in the shell, but I'm not 100% sure on that.

I use break main if (strcmp (basename (argv[0]), "world") == 0) to create a breakpoint that will only be hit in the world executable. You can do just break main but you'll also hit this in the shell, but just continue to keep going and eventually you'll stop in the correct main function. The conditional breakpoint just means GDB does the check for me. Of course, this relies on basename and strcmp being linked into your executable.

What I don't know is how you'd do this in VS Code, but hopefully they provide a GDB console where you could input the above commands directly.

Sign up to request clarification or add additional context in comments.

1 Comment

I have just updated the post for adding the "step into" error, please check the updated post.
4

I assume that your real use case is more complicated and you need to debug world in the environment and/or with IPC set up by hello.

I further assume that creating a simulation environment might be too much effort.

I had a similar requirement in a system where several programs were started from a main program, connected by pipes, FIFOs and databases. It was not easily possible to run the child programs separately.

I used the following approach to attach the debugger to the program world:

  • Modify the program world to wait before the interesting part and build this version.
int main(int argc, char **argv)
{
    { /* begin additional code */
        static volatile int debugwait = 1;
        while(debugwait);
    } /* end of additional code */

    printf("Hello World");
    return 0;
}
  • Run the program hello and wait for the worldprocess to be started.
  • Attach the debugger to the running world process.
  • Set breakpoints as necessary.
  • Modify the variable debugwait = 0 to allow the program to terminate the loop.
  • Continue or single-step the program.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.