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.

3

3 Answers 3

6

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
Sign up to request clarification or add additional context in comments.

1 Comment

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.
5

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

2 Comments

Thanks for info, it is exactly what I was missing. Hope it will be part of official release soon.
@Michy, it's part of official releases for some years - maybe you thus want to change the accepted answer.
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>

2 Comments

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.
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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.