Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gdb how to execute target program from script

I want to debug a program, using gdb. But I invoke that program through a script.

How can I use gdb? The script is long and its not possible for me to invoke the program directly using command line arguments from gdb.

Also the process that is created when the script starts is short lived so can't attach gdb to the process.

What I want to do is something like, start gdb with that program, add my breakpoints then execute the script (FYI - it also takes arguments), then when it hits breakpoint do whatever I want.

I looked at shell option in gdb, but that spawns a new shell if I am not wrong and return to gdb when done. This is not what I want.

Please let me know if there is a better way.

like image 818
L Lawliet Avatar asked Aug 12 '14 21:08

L Lawliet


People also ask

How do I run a program under gdb?

Starting your program. Use the run command to start your program under GDB. You must first specify the program name (except on VxWorks) with an argument to GDB (see section Getting In and Out of GDB), or by using the file or exec-file command (see section Commands to specify files).

How do I run a script in gdb?

Execute commands from a script The commands in a script file are exactly the same as commands on the gdb command line. You can specify the script name when you are starting GDB using execute script switch ( -x ). You can also execute a GDB script inside GDB using source command.

How do you pass command-line arguments to a program when using gdb?

You can optionally have gdb pass any arguments after the executable file to the inferior using --args . This option stops option processing. This will cause gdb to debug gcc , and to set gcc 's command-line arguments (see Arguments) to ` -O2 -c foo. c '.

How do you call a function in gdb?

The simplest is to cast the call to the function's declared return type. For example: (gdb) p getenv ("PATH") 'getenv' has unknown return type; cast the call to its declared return type (gdb) p (char *) getenv ("PATH") $1 = 0x7fffffffe7ba "/usr/local/bin:/"...


2 Answers

There are several ways.

The truly old-school way is to hack a loop into your program's main like:

volatile int zzz;
...
int main() {
  while (!zzz) sleep (1);

Then, run your script. In a separate window, run gdb on the program you want to debug, and use attach to attach to the sleeping program. Then you can set breakpoints, etc, and finally:

(gdb) set var zzz = 1
(gdb) cont

A slightly newer ("new" as in "it's been in gdb at least 10 years") way is to edit your script and put a gdb --args before the invocation of the program you want to debug. This method doesn't always work, though. It doesn't handle redirections properly, among other things.

Finally, you can use multi-inferior debugging. This is the "newest" approach of all. Here I'm following my own blog post on the topic:

$ gdb /bin/sh  # or whatever runs your script
(gdb) set args arguments-to-the-script
(gdb) set detach-on-fork off
(gdb) set target-async on
(gdb) set non-stop on
(gdb) set pagination off

Then you can do something like:

(gdb) add-inferior -exec program-you-want-to-debug

... then switch to that inferior and set breakpoints. Now switch back to the first inferior and run -- it should all work!

like image 176
Tom Tromey Avatar answered Sep 28 '22 01:09

Tom Tromey


A couple of methods I have used in the past.

  1. Rename yourprog to yourprog.real. Make a script named yourprog that runs gdb --args yourprog.real "$@".
  2. Make yourprog invoke gdb on its own pid, then call sleep in a loop.
like image 21
n. 1.8e9-where's-my-share m. Avatar answered Sep 28 '22 02:09

n. 1.8e9-where's-my-share m.