Lone Learner
Lone Learner

Reputation: 20628

How can I use the output of a shell command as an argument to GDB command within GDB?

I don't want to spend time searching for the PID of the process I want to attach to, so I do something like this,

gdb -p ($pidof foo)

where foo is the process name.

I want to know if I can so something like this from within GDB.

I am looking for something like the following.

(gdb) attach $(pidof foo)
Illegal process-id: $(pidof foo).
(gdb) attach `pidof foo`
Illegal process-id: `pidof foo`.

Is there anything like this in GDB?

Upvotes: 3

Views: 2370

Answers (1)

pmod
pmod

Reputation: 10997

Gdb attach command requires process id as an argument. So, you cannot achieve it directly. You can do it in two steps:

(gdb) shell pidof foo
12345
(gdb) attach 12345
Attaching to process 12345
...

But gdb is quite flexible and can be extended with internal scripting (known as Canned Sequences of Commands), python, etc. Here is an example script that also handles situations when no process found or when several processes found (the first given by pidof is selected):

define attach_pidof
  if $argc != 1
   help attach_pidof
  else
   shell echo -e "\
set \$PID = "$(echo $(pidof $arg0) 0 | cut -d ' ' -f 1)"\n\
if \$PID > 0\n\
  attach "$(pidof -s $arg0)"\n\
else\n\
  print \"Process '"$arg0"' not found\"\n\
end" > /tmp/gdb.pidof
   source /tmp/gdb.pidof
  end
end
document attach_pidof
Attach to process by name.
Usage: attach_pidof PROG_NAME
end

Here I used trick pointed out by @dbrank0 (echo'ing to file and then running it with source). Also, I am using echo $(pidof <>) 0 to provide default value 0 when no process found.

Place this to ~/.gdbinit so on gdb start, this command will be automatically added to gdb and can be used:

(gdb) attach_pidof myprog 

If your gdb supports python extensions, you can place this to some file, e.g. ext.py:

import gdb
from subprocess import check_output, CalledProcessError

class AttachPidofCommand (gdb.Command):
  "Attach to process by name"

  def __init__ (self):
    super (AttachPidofCommand, self).__init__ ("attach_pidof",
                         gdb.COMMAND_SUPPORT,
                         gdb.COMPLETE_NONE, True)

  def invoke (self, arg, from_tty):
    try:
        pid = check_output(["pidof", arg]).split()[0].decode("utf-8")
    except CalledProcessError:
        gdb.write('process \'%s\' not found\n' % (arg))
        return
    gdb.write('attach to \'%s\' (%s)\n' % (arg, pid))
    gdb.execute('attach %s' % (pid), from_tty)

AttachPidofCommand()

import and use the same way:

(gdb) source ext.py
(gdb) attach_pidof my_prog

Upvotes: 4

Related Questions