1

I would like to store the executable name of the current inferior in a variable. I way to obtain the executable name in the gdb CLI is the following:

 pipe info inferiors | awk '{ if ($1 == "*") { print $4} }'

But I am unable to store the output of this expression in a variable. The expression uses single and double quotes, which makes gdb complain if it is combined with set and eval.

(gdb) set $exec="pipe info inferiors | awk '{ if ($1 == "*") { print $4} }'"
Argument to arithmetic operation not a number or boolean.
(gdb) eval "!echo %s", "pipe info inferiors | awk '{ if ($1 == "*") { print $4} }'"
Argument to arithmetic operation not a number or boolean.

Then, how can I store the executable name in a variable? My goal is to pass the executable name to the file command to reload the executable when Autotools are used (see using libtool e gdb).

Gorka
  • 1,971
  • 1
  • 13
  • 28

2 Answers2

1

Your best bet is to use embedded Python. Example:

gdb -q ./a.out
Reading symbols from ./a.out...

(gdb) start
Temporary breakpoint 1 at 0x1129: file foo.c, line 3.
Starting program: /tmp/a.out 

Temporary breakpoint 1, main () at foo.c:3
3         int v1 = 1, v2 = 2, v3 = 42;
(gdb) info inferiors
  Num  Description       Connection           Executable        
* 1    process 217200    1 (native)           /tmp/a.out        

(gdb) python gdb.execute('set $pid = ' + str(gdb.selected_inferior().pid))
(gdb) p $pid
$1 = 217200

Update:

Original question asked for field 4, which is the pid, but it appears that Gorka was actually interested in the file name, which can be found this way:

(gdb) python gdb.execute('set $f = "' + str(gdb.selected_inferior().progspace.filename) + '"')
(gdb) p $f
$2 = "/tmp/a.out"

Documentation: Inferiors, Progspaces

Update 2:

Now I get the file name again with the field 4... but I was obtaining the pid as you said. I cannot figure why this is happening.

You get pid or name depending on whether the inferior is running or not (that's the danger of parsing data that is intended for humans).

When the inferior is not running, info inferiors prints:

(gdb) info inferiors
  Num  Description       Connection           Executable
* 1    <null>                                 /bin/date

When the inferior is currently active, it prints:

(gdb) info inferiors
  Num  Description       Connection           Executable
* 1    process 118431    2 (native)           /bin/date
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • To get the executable name, I have used `gdb.execute('set $exec = "' + str(gdb.selected_inferior().progspace.filename) + '"')`. Thanks for pointing the right direction. – Gorka May 31 '20 at 16:41
  • 1
    @Gorka Your `pipe` command produced pid, so I gave you that (I originally misunderstood and actually gave the `filename` answer, before editing it to give `pid`). If this answer gave you what you need, you should accept it. – Employed Russian May 31 '20 at 16:54
  • Sorry about the confusion. – Gorka May 31 '20 at 21:02
  • Now I get the file name again with the field 4... but I was obtaining the pid as you said. I cannot figure why this is happening. – Gorka Jun 02 '20 at 23:35
  • thanks for clarifying it! It clearly shows the relevance of your solution. – Gorka Jun 03 '20 at 00:37
0

Although @EmployedRussian's answer is the most appropriated solution for the use case presented in the question, I think that the question of how to use pipe and awk to set a variable has not been answered yet. This could be done using python and splitting the pipe in two parts:

python res = gdb.execute('info inferiors', to_string=True);
python gdb.execute ('set $exec = "' + str(res.strip().split()[6]) + '"');

If a awk like command is preferred, try with the tools provided by python, for instance, convert res to a pandas DataFrame.

Note that, this approach could be catastrophic as has been seen here with the column selection issue.

Gorka
  • 1,971
  • 1
  • 13
  • 28