Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute finish and then another command from inside commands?

Tags:

c

gdb

This is a reduced example of the structure of my code:

void increment(int j);

int main()
{
  int i = 0;

  while(1) {
    i = increment(i);
  }

  return 0;
}

int increment(int j)
{
  return j + 1;
}

And here is the corresponding GDB script:

b increment
command 1
finish
print i
continue
end

The problem is that the finish command prevents the commands that come after it (namely print i and continue) to not be called.

Is there a way to tell GDB to print i right after any increment call?

like image 589
Randomblue Avatar asked May 08 '12 14:05

Randomblue


People also ask

How do you run & commands one after the other?

1) Concatenate commands with the Semicolon operator (;) If you want to execute all commands regardless of whether the previous ones failed or not, separate them with semicolons. This executes all commands one after another. For instance: Just enter the following three commands in one line, separated by semicolons.

How do you run a command after the previous finished in Linux?

Using the && Operator. We should note that the && operator executes the second command only if the first one returns an exit code of 0. If we want to run the next script, even if the first one fails, we can replace the && operator with the; operator, which runs the next command regardless of the exit code.


2 Answers

You can apparently work around this bug by wrapping all the commands in a single python invocation e.g.

(gdb) break doSomething
Breakpoint 1 at 0x400478: file iter.c, line 5.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>python gdb.execute("print i"); gdb.execute("finish"); gdb.execute("print i");
>end

Breakpoint 1, doSomething () at iter.c:5
5     while (i < 5)
$1 = 0
main (argc=1, argv=0x7fffffffe178) at iter.c:13
13    return 0;
$2 = 5

edit: a 2nd work around that doesn't require python appears to be defining a new gdb command and running that in commands:

define foo
print *i
set $addrOfI = i
finish
print *$addrOfI
end

break doSomething
commands
foo
end
like image 117
matt Avatar answered Oct 18 '22 08:10

matt


The problem is that finish seems to stop abort the commands set for the first breakpoint after it.

This is expected behavior: any command that resumes the inferior (being debugged) process (as finish does) also stops the execution of canned command sequence.

Update:

See also this GDB bug report.

Is there a way to tell GDB to print i right after any increment call?

Yes:

  1. Diassemble increment routine using disas command. Find ret instruction at the end of it (there will only be one).
  2. Set a breakpoint on that instruction, using break *0xNNNNN syntax.
  3. Attach a command to that breakpoint:

    command N
     print $rax    # or $eax if you are on 32-bit x86 platform
     continue
    end
    

Voila: you should get values being returned from increment() printed (just before being returned).

like image 42
Employed Russian Avatar answered Oct 18 '22 09:10

Employed Russian