12

Is it possible to have gdb attached to the PID of a running process and every time the program hits a particular breakpoint have gdb output the stackframe to an external file?

I've had a look at this and this but there is no mention on whether it is possible to attach gdb to an already running process (instead of having gdb launch it).

I can otherwise attach gdb to the PID just fine, but I'd like to automate it to run bt, store the output in an external file and then run continue. At the moment I'm doing this manually and it's a pain when I have to do it every time a breakpoint is hit.

Community
  • 1
  • 1
Nobilis
  • 7,310
  • 1
  • 33
  • 67
  • Okay, that's pretty direct :) It's just that it seemed like gdb could be automated to carry out some commands when it launches a program, and since you can examine a running pid in much the same way as one that you've just launched it felt like it was possible. – Nobilis Jul 16 '13 at 09:34
  • Well of course it is possible to attach gdb to a running process. It is basic required functionality of any debugger. Have you tried `man gdb`? It's there. – n. m. could be an AI Jul 16 '13 at 09:38
  • 1
    @Nobilis and I am wrong you got some promising answers – Grijesh Chauhan Jul 16 '13 at 09:39
  • @n.m. I can attach it just fine, that's not the problem. The problem is that I want it to automatically print the stackframe when the program hits a breakpoint and store the output in an external file. Ideally have gdb run bt when the program hits a breakpoint`, save the output of bt somewhere and then run continue – Nobilis Jul 16 '13 at 09:57

2 Answers2

8
Is it possible to have gdb attached to the PID of a running process??

Yes. Possible.

Updated:

Step 1:

In .gdbinit file add the following command,

define callstack
     set $Cnt = $arg0

     while($Cnt)
        commands $Cnt
        silent
        bt
        c
        end
        set $Cnt = $Cnt - 1
     end
end

Step 2: Invoke the gdb with -x <path to .gdbinit file >. Remember PID also for running process.

Step 3: Put Break points, whereever you need.

Step 4: Call the user defined command callstack and pass no .of break points.

    gdb> callstack <No.of. Break Points> 

Step 5: Now give 'c' to continue. Bcos process is already running.

For Logging I suggest to follow @VoidPointer's answer.

set pagination off
set logging file gdb.txt
set logging on 

works for me. Reference.

Jeyaram
  • 9,158
  • 7
  • 41
  • 63
  • I should probably clarify that I have access to the source and the program is compiled with debug symbols so when I attach gdb to it, I can set up breakpoints freely, have a look at the functions, when printing the stack frame I get all the names etc. Will this make any difference? – Nobilis Jul 16 '13 at 09:41
  • The above steps put the break point to all the functions in your process. Those function names will be in `function_names` file. For collection function names, I'm using `nm` tools which needs object file, not executable. so you need to generate object files using -c option. – Jeyaram Jul 16 '13 at 09:45
  • I only want a breakpoint at a particular line, as I have debugging symbols I can access the line just fine and set a breakpoint there. I won't need all the function names in there. Is it possible to just set a breakpoint, run backtrace there and then store that output? – Nobilis Jul 16 '13 at 09:49
  • Thanks very much! I'll try this and I'll get back to you :) – Nobilis Jul 16 '13 at 09:58
  • I'm probably doing something wrong can you please help me? I ran gdb like this ` gdb -p 3580 -x ./.gdbinit` after I saved the code in the gdbinit file. I set a breakpoint where I needed (`b sourcefile.c:3535`), called `callstack 1` and then `run` and the program exited. Also how do I print the results of `callstack` to an external file? Is it possible to say have `gdb` run in the background and have stdout redirected to a file? Thanks! – Nobilis Jul 16 '13 at 10:12
  • Process is already running right?? so just give `c` after `callstack 1`. – Jeyaram Jul 16 '13 at 10:20
6

If what you need is to automate printing stack-frame using gdb when knowing PID and functions then you can try this.. (Given minimal code to be functional)

/root/.gdb_init:

set pagination off
set logging file gdb.txt
set logging on

br fun_convert
# ^^ when breaking at function fun_convert, execute `commands` till next `end`
commands
    bt
    print "Sample print command 1 \n"
    continue
end

br file.c:451
# ^^ when breaking at line 451 of file.c, execute from `commands` till next `end`
commands
    bt
    print "Sample print command 2 \n"
    continue
end

continue

Invoking GDB for PID 6474 and command file /root/.gdb_init,

gdb -p 6474 -x /root/.gdb_init

Here, fun_convert is the function to break. This br is actual break gdb-command and you can also break at any line of file using br file.c:451. For more break options, check gdb help. You can add any gdb-commands you need between commands and end for corresponding br. For more info on commands, check help commands on gdb.

Note: SO's JS is broken on my browser, please pardon any mistakes and feel free to correct. Also can't add comments :(

VoidPointer
  • 3,037
  • 21
  • 25
  • Cool, how do I run this from the command line, sorry? Also, does this depend on the breakpoint I've set or whenever `fun_convert` for example is called? – Nobilis Jul 16 '13 at 09:52
  • For example instead of `b fun_convert` can I do `b 451` where 451 is the line number? – Nobilis Jul 16 '13 at 09:54
  • Thanks for your answer, I chose Jeyaram's solution as this worked for me but I upvoted your answer for the `set` commands you had provided :) – Nobilis Jul 16 '13 at 11:09