5

Is there any way how to pipe output of internal gdb command to some shell command like grep - the variant of [cmd] ! grep in mdb?

To be more clear: in solaris mdb you can e.g. write

main::dis ! grep call

to detect which functions are called from the main (or grep some register names to see how it is changed). I am interested if there is such possibility to do so just in gdb without necessarity to switching from gdb.

Michy
  • 623
  • 9
  • 15
  • 1
    Maybe it's time to start looking into Python scripting to define new commands: http://stackoverflow.com/questions/4060565/how-to-script-gdb-with-python-example-add-breakpoints-run-what-breakpoint-d :-) – Ciro Santilli OurBigBook.com Jul 02 '15 at 18:30
  • I believe this is what you're looking for https://unix.stackexchange.com/questions/456294/gdb-in-one-command – rinogo Aug 16 '19 at 17:43
  • For example, `gdb -p 1234 -batch -ex 'bt'` prints a backtrace for process 1234. – rinogo Aug 16 '19 at 17:50

3 Answers3

4

Seven years later, I still have not found a native way to do this, so I wrote the shell-pipe gdb extension. Its complete source code is replicated here for completeness.

from __future__ import print_function

import gdb
import string
import subprocess
import sys


class ShellPipe (gdb.Command):
    "Command to pipe gdb internal command output to external commands."

    def __init__(self):
        super (ShellPipe, self).__init__("shell-pipe",
                gdb.COMMAND_DATA,
                gdb.COMPLETE_NONE, True)
        gdb.execute("alias -a sp = shell-pipe", True)

    def invoke(self, arg, from_tty):
        arg = arg.strip()
        if arg == "":
            print("Argument required (gdb_command_and_args | externalcommand..).")
            return

        gdb_command, shell_commands = None, None

        if '|' in arg:
            gdb_command, shell_commands = arg.split("|", maxsplit=1)
            gdb_command, shell_commands = gdb_command.strip(), shell_commands.strip()
        else:
            gdb_command = arg

        # Collect the output and feed it through the pipe
        output = gdb.execute(gdb_command, True, True)
        if shell_commands:
            shell_process = subprocess.Popen(shell_commands, stdin=subprocess.PIPE, shell=True)
            shell_process.communicate(output.encode('utf-8'))
        else:
            sys.stdout.write(output)

ShellPipe()

After sourcing ShellPipeCommand.py in $HOME/.gdbinit, one can now pipe internal gdb commands to external shell commands.

    (gdb) shell-pipe disas | grep main
    0x0000000000400527 <+1>:     mov    %rsp,%rbp
    0x000000000040052e <+8>:     movq   $0x4005e4,-0x8(%rbp)
 => 0x0000000000400536 <+16>:    mov    -0x8(%rbp),%rax
    0x000000000040053a <+20>:    mov    %rax,%rdi
merlin2011
  • 71,677
  • 44
  • 195
  • 329
  • I enhanced your script a little to allow output redirection with > as well. This works in linux at least. After the `if '|' in arg:` I added an `elif '>' in arg:` and prepended `cat > ` to the `shell_commands` variable. – piCookie Dec 09 '19 at 17:46
4

I am not sure if I have understood your question correctly. If you want to a log results of your GDB commands that you ran during a debug session, then Yes there is support for this from GDB.

show logging                    # displays weather logging is on / off
set logging on                  # enable logging
set logging off                 # disable logging
set logging file log-file.txt   # set name for log file, default is gdb.txt

the log file will be generated in your current directory.

Further you can append logs of debug sessions or create new on every debug session using

set logging overwrite <on/off>
Kamath
  • 4,461
  • 5
  • 33
  • 60
  • Thank you for your answer. The logging is not exactly what I am searching for. In the Solaris mdb there is a possibility to write e.g. 'main::dis ! grep call' and the debugger will call grep on the disasembly result. I am searching for the similar way to do so in the gdb - run grep of dissasemble command output (or send it to the less). I could use e.g. objdump and grep its result or get the output from the logging file you mentioned, but I am interested if there is way to do it just inside the gdb. – Michy Aug 19 '11 at 13:04
  • 1
    don't forget to set pagination off.... logging/shell command is currently the only way to do it e.g. set logging on, disas main, set logging off, shell grep call gdb.txt, someone is working on a pipe command, which should may make this more straight forward – matt Aug 19 '11 at 15:26
1

A new GDB command has been introduced, namely pipe. If you want to process the output of a GDB command using some shell command or some script, that can be done using this new command.

https://sourceware.org/gdb/onlinedocs/gdb/Shell-Commands.html

pipe [command] | shell_command
feilong
  • 3
  • 3
Abhijit
  • 199
  • 4
  • Thanks for info, it is exactly what I was missing. Hope it will be part of official release soon. – Michy Jan 10 '12 at 09:24
  • @Michy, it's part of official releases for some years - maybe you thus want to change the accepted answer. – maxschlepzig Aug 10 '23 at 23:05