Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Break on variable being freed

There's a way to break on a variable/memory address being freed ? Does a simple watchpoint work on this case ?

Scenario, I getting a segfault when the program does the freeing of variables apparently the variable in question is getting free two times, i need know where it's first freed.

PS: lldb and gdb, if possible for both respective commands.

like image 600
Victor Aurélio Avatar asked Dec 30 '25 21:12

Victor Aurélio


1 Answers

How to do it in gdb

In gdb you can set conditional breakpoints by writing break location if condition.

This means that in order to break on free where the function is invoked with a pointer that refers to some dynamically allocated data, we first have to obtain the address of the dynamically allocated data, and then set a breakpoint with a suitable condition.

Further reading:

  • sourceware.org :: Conditions - Debugging with gdb
  • fayewilliams.com - GDB Conditional Breakpoints


Setting up the experiment

/tmp% cat > foo.c <<EOF
> #include <stdlib.h>
> 
> void some_function (int * p) {
>   free (p);
> }
> 
> int main () {
>   int * p = malloc (sizeof (int));
> 
>   some_function (p);
> 
>   free (p);
> 
>   return 0;
> }
> EOF
/tmp% gcc -g foo.c -o a.out

The Adventure

/tmp% gdb ./a.out

The first thing we need to do is find a suitable breakpoint so that we can expect the contents of the variable we would like to watch, more specifically the address of the dynamically allocated memory.


(gdb) list main
2   
3   void some_function (int * p) {
4     free (p);
5   }
6   
7   int main () {
8     int * p = malloc (sizeof (int));
9   
10    some_function (p);
11

We will then set a breakpoint on a suitable place, in this case line 9 — we then run the application to see what the value stored in p is.


(gdb) break 9
Breakpoint 1 at 0x400577: file foo.c, line 9.
(gdb) run
Starting program: /tmp/a.out 

Breakpoint 1, main () at foo.c:10
(gdb) print p
$1 = (int *) 0x601010

When we know the address we would like to monitor in terms of free, we can easily set a conditional breakpoint at our desired location. First we will need to make sure that free is actually named what we think.

(gdb) disas main
Dump of assembler code for function main:
   0x0000000000400561 : push   %rbp
   0x0000000000400562 : mov    %rsp,%rbp
   0x0000000000400565 : sub    $0x10,%rsp
   0x0000000000400569 : mov    $0x4,%edi
   0x000000000040056e :    callq  0x400440 <malloc@plt>
   0x0000000000400573 :    mov    %rax,-0x8(%rbp)
=> 0x0000000000400577 :    mov    -0x8(%rbp),%rax
   0x000000000040057b :    mov    %rax,%rdi
   0x000000000040057e :    callq  0x400546 <some_function>
   0x0000000000400583 :    mov    -0x8(%rbp),%rax
   0x0000000000400587 :    mov    %rax,%rdi
   0x000000000040058a :    callq  0x400410 <free@plt>
   0x000000000040058f :    mov    $0x0,%eax
   0x0000000000400594 :    leaveq 
   0x0000000000400595 :    retq

We can now create the breakpoint, and continue execution to see where our data is freed:

(gdb) break free@plt if $rdi == 0x601010
Breakpoint 2 at 0x400410 (3 locations)
(gdb) cont
Continuing.

Breakpoint 2, 0x0000000000400410 in free@plt ()
(gdb) backtrace
#0  0x0000000000400410 in free@plt ()
#1  0x000000000040055e in some_function (p=0x601010) at foo.c:4
#2  0x0000000000400583 in main () at foo.c:10
(gdb) cont
Continuing.

Breakpoint 2, 0x0000000000400410 in free@plt ()
(gdb) backtrace
#0  0x0000000000400410 in free@plt ()
#1  0x000000000040058f in main () at foo.c:12
(gdb) cont
Continuing.
*** Error in `/tmp/a.out': double free or corruption (fasttop): 0x0000000000601010 ***
...
like image 75
Filip Roséen - refp Avatar answered Jan 02 '26 11:01

Filip Roséen - refp