Watchpoint on memory writes for a local static?

2.1k Views Asked by At

I want to set a watchpoint on the static local s_db:

static sqlite3*& GetSqliteDb()
{
    static std::once_flag flag;
    static sqlite3* s_db = NULL;

    std::call_once(flag, []() {
        s_db = ...
        ...
    });
}

I've tried setting a watchpoint with file::function::name, but its giving me trouble:

$ gdb
GNU gdb (GDB) 7.6.2
Copyright (C) 2013 Free Software Foundation, Inc.
...
(gdb) file ./bin/Debug/ac-test 
Reading symbols from ...
(gdb) watch ac-sqlite.cpp::GetSqliteDb::s_db
No symbol "ac" in current context.
(gdb) watch "ac-sqlite.cpp::GetSqliteDb::s_db"
Cannot watch constant value `"ac-sqlite.cpp::GetSqliteDb::s_db"'.
(gdb) watch GetSqliteDb()::s_db
A syntax error in expression, near `s_db'.
(gdb) watch GetSqliteDb::s_db
No symbol "s_db" in specified context.
(gdb) watch s_db
No symbol "s_db" in current context.
(gdb) 

For completeness, I built with -O0 -g3, so even symbolic constant names are available.

How do I set a watchpoint for writes on the static local s_db?

2

There are 2 best solutions below

0
On

It seems that if I set a watchpoint with a mangled C++ name then everything is OK. If I set a watchpoint with a demangled C++ name then gdb does not find a static varable in a function. This is an example that I tested with gcc and gdb on Windows:

void GetSqliteDb()
{
  static int *s_db = 0;
  s_db = new int;
  *s_db = 1;
  *s_db = 2;
   s_db = 0;
}

int main()
{
   GetSqliteDb();
   return 0;
}

This is nm output:

>nm a.exe | grep s_db
00405020 b __ZZ11GetSqliteDbvE4s_db

>nm a.exe | grep s_db | c++filt
00405020 b GetSqliteDb()::s_db

This is a gdb session:

>gdb -q a.exe
Reading symbols from a.exe...done.
(gdb) watch GetSqliteDb::s_db
No symbol "s_db" in specified context.
(gdb) watch _ZZ11GetSqliteDbvE4s_db
Hardware watchpoint 1: _ZZ11GetSqliteDbvE4s_db
(gdb) start
Temporary breakpoint 2 at 0x4013cb: file main.cpp, line 11.
Starting program: a.exe
[New Thread 1688.0xff8]

(gdb) info watchpoints
Num     Type           Disp Enb Address    What
1       hw watchpoint  keep y              _ZZ11GetSqliteDbvE4s_db

Temporary breakpoint 2, main () at main.cpp:11
11      {
(gdb) c
Continuing.
Hardware watchpoint 1: _ZZ11GetSqliteDbvE4s_db

Old value = 0
New value = 4007328
GetSqliteDb () at main.cpp:5
5         *s_db = 1;
(gdb) c
Continuing.
Hardware watchpoint 1: _ZZ11GetSqliteDbvE4s_db

Old value = 4007328
New value = 0
GetSqliteDb () at main.cpp:8
8       }
(gdb) c
Continuing.
[Inferior 1 (process 1688) exited normally]

Update


I tested the same example on RHEL 6.3 (2.6.32-279.el6.x86_64) with gdb 7.6.2 and it sets a watchpoint correctly. So I cannot reproduce the problem on this platform:

>gdb a.out
GNU gdb (GDB) 7.6.2
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/a.out...done.
(gdb) watch GetSqliteDb::s_db
Hardware watchpoint 1: GetSqliteDb::s_db
(gdb) r
Starting program: /home/a.out
Hardware watchpoint 1: GetSqliteDb::s_db

Old value = (int *) 0x0
New value = (int *) 0x601010
GetSqliteDb () at main.cpp:5
5         *s_db = 1;
(gdb) c
Continuing.
Hardware watchpoint 1: GetSqliteDb::s_db

Old value = (int *) 0x601010
New value = (int *) 0x0
GetSqliteDb () at main.cpp:8
8       }
(gdb)
1
On

It seems that you need to dereference the address of s_db variable with * operator.
See Setting Watchpoints in documentation. This watchpoint should work:

(gdb) watch *("ac-sqlite.cpp::GetSqliteDb::s_db")