gdb: Cast memory address to an STL object - c++

I have a memory address that i know is an STL object. Say the address is 0x603340, and I know there is a map there
How do I display the contents of this memory as said object from gdb?
I tried this:
p ('std::map<std::string, std::string*, std::less<std::string>, std::allocator<std::pair<std::string const, std::string*> > >'*) 0x603340
which gets me:
No symbol "std::map<std::string, std::string*, std::less<std::string>, std::allocator<std::pair<std::string const, std::string*> > >" in current context.
Any idea what am I doing wrong? Thanks.

I have taken this as a first step: simple stl containers inspectors for gdb. I did not manage to use pmap directly but I made use of it and create my own scrupt my_pmap:
>cat my.txt
define my_pmap
set $my_obj = *((std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::string*, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::string*> > >*) $arg0)
print $my_obj
set $i = 0
set $node = $my_obj._M_t._M_impl._M_header._M_left
set $end = $my_obj._M_t._M_impl._M_header
set $tree_size = $my_obj._M_t._M_impl._M_node_count
while $i < $tree_size
set $value = (void *)($node + 1)
printf "elem[%u].left: ", $i
p *( std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)$value
set $value = $value + sizeof(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)
printf "elem[%u].right: ", $i
p **((std::basic_string<char, std::char_traits<char>, std::allocator<char> >**)$value)
if $node._M_right != 0
set $node = $node._M_right
while $node._M_left != 0
set $node = $node._M_left
end
else
set $tmp_node = $node._M_parent
while $node == $tmp_node._M_right
set $node = $tmp_node
set $tmp_node = $tmp_node._M_parent
end
if $node._M_right != $tmp_node
set $node = $tmp_node
end
end
set $i=$i+1
end
printf "Map size = %u\n", $tree_size
end
Then I wrote a short C++ test program:
#include <map>
#include <string>
#include <iostream>
int main()
{
std::string local_s1 = "Local1";
std::string local_s2= "Local2";
typedef std::map<std::string, std::string*> my_type_t;
my_type_t my_map;
my_map.insert(std::make_pair("Key-string-1", &local_s1));
my_map.insert(std::make_pair("Key-string-2", &local_s2));
my_map.insert(std::make_pair("Key-string-3", &local_s2));
return 0;
}
And then I tested my script:
>gdb -q ./a.out
Reading symbols from /import/home/sergey.kurenkov/src/linux.x64.6.0/tests/test.gdb_map/a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x400c7c: file main.cpp, line 7.
Starting program: /import/home/sergey.kurenkov/src/linux.x64.6.0/tests/test.gdb_map/a.out
Temporary breakpoint 1, main () at main.cpp:7
7 std::string local_s1 = "Local1";
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6.x86_64
(gdb) source my.txt
(gdb) n
8 std::string local_s2= "Local2";
(gdb)
11 my_type_t my_map;
(gdb)
12 my_map.insert(std::make_pair("Key-string-1", &local_s1));
(gdb)
13 my_map.insert(std::make_pair("Key-string-2", &local_s2));
(gdb)
14 my_map.insert(std::make_pair("Key-string-3", &local_s2));
(gdb)
16 return 0;
(gdb) p &my_map
$1 = (my_type_t *) 0x7fffffffe040
(gdb) my_pmap 0x7fffffffe040
elem[0].left: $2 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603088 "Key-string-1"}}
elem[0].right: $3 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603028 "Local1"}}
elem[1].left: $4 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x6030f8 "Key-string-2"}}
elem[1].right: $5 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603058 "Local2"}}
elem[2].left: $6 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603168 "Key-string-3"}}
elem[2].right: $7 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603058 "Local2"}}
Map size = 3
(gdb)

Related

print contents of std::vector<std::string> in lldb

I want to print all the strings in a vector. When I do
(lldb) p myVector
(std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) $30 = size=65 {
[0] = Summary Unavailable
[1] = Summary Unavailable
[2] = Summary Unavailable
[3] = Summary Unavailable
[4] = Summary Unavailable
[5] = Summary Unavailable
[6] = Summary Unavailable
[7] = Summary Unavailable
[8] = Summary Unavailable
[9] = Summary Unavailable
[10] = Summary Unavailable
[11] = Summary Unavailable
...
However, printing individual elements work e.g.,
p myVector[5].c_str()
(const std::basic_string<char, std::char_traits<char>, std::allocator<char> >::value_type *) $31 = 0x0000600000210280 "-D__STDC_CONSTANT_MACROS"
I'd like to print all elements at once as there are quite a few.
Add -fstandalone-debug to the compiler command line.
I have this set on my cmake for the debug build:
set(CMAKE_CXX_FLAGS_DEBUG_INIT "-ggdb3 -O0 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fstandalone-debug ${SANITIZE_OPTS}" CACHE STRING "Initial debug flags")
So i was able to solve this by using lldb's expr evaluation
(lldb) expr -- for (int x = 0; x < myVector.size(); x++) printf("arg[%d] = %s\n", x, myVector[x].c_str())
# prints:
arg[0] = /Library/Developer/CommandLineTools/usr/bin/c++
arg[1] = --driver-mode=g++
arg[2] = -DGTEST_HAS_RTTI=0
arg[3] = -D__STDC_CONSTANT_MACROS
arg[4] = -D__STDC_FORMAT_MACROS
arg[5] = -D__STDC_LIMIT_MACROS
...

Terminal use gdb to debug .cpp files, (gdb)p command

When I use gdb to debug, I just want to use '(gdb)p x' to print the value of x, but the result is very complicated. Terminal command like this:
(gdb) p word
Output:
$2 = {<std::__1::__basic_string_common<true>> = {<No data fields>}, static __short_mask = 1,
static __long_mask = 1,
__r_ = {<std::__1::__compressed_pair_elem<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, 0, false>> = {__value_ = {{__l = {__cap_ = 1970239750,
__size_ = 0, __data_ = 0x0}, __s = {{__size_ = 6 '\006', __lx = 6 '\006'},
__data_ = "you", '\000' <repeats 19 times>}, __r = {__words = {1970239750, 0,
0}}}}}, <std::__1::__compressed_pair_elem<std::__1::allocator<char>, 1, true>> = {<std::__1::allocator<char>> = {<No data fields>}, <No data fields>}, <No data fields>},
static npos = 18446744073709551615}
What I really want is __data_ = "you" this segment only.
How can I get a simple result like this:
$2 = "you"
Can someone help me? Very appreciate that.
How can I get a simple result like this:
That's what GDB pretty-printers are for.
It looks like you are using libc++ (and probably Clang).
From libc++ documentation:
GDB does not support pretty-printing of libc++ symbols by default. However, libc++ does provide pretty-printers itself. Those can be used as:
$ gdb -ex "source <libcxx>/utils/gdb/libcxx/printers.py" \
-ex "python register_libcxx_printer_loader()" \
<args>
You can put the source <libcxx>/utils/gdb/libcxx/printers.py and the python register_libcxx_printer_loader() commands into your ~/.gdbinit, and then things will just work™.

Coredump of qt application after qt upgrade

After a Yocto upgrade to warrior and with this an qt upgrade from 5.9.7 to 5.12.8 our qt qml application crashes on the device if the user scrolls (keyboard event) through a listview. It crashes in QV4::MarkStack::drain (QmlEngine GarbageCollector) and we have no idea where the problem could be.
Any advise how to find such an error?
Here is a backtrace:
Thread 1 (LWP 516):
#0 0x0000001c in ?? ()
No symbol table info available.
#1 0xb695a9d0 in QV4::MarkStack::drain (this=this#entry=0xbee86804) at ../../include/QtQml/5.12.8/QtQml/private/../../../../../../git/src/qml/memory/qv4heap_p.h:73
h = <optimized out>
#2 0xb69b9904 in QV4::PersistentValueStorage::mark (this=<optimized out>, markStack=markStack#entry=0xbee86804) at /usr/src/debug/qtdeclarative/5.12.8+gitAUTOINC+101799f8ac-r0/git/src/qml/jsruntime/qv4persistent.cpp:243
p = 0xb0078000
#3 0xb695b4fe in QV4::MemoryManager::collectRoots (this=this#entry=0x1099c68, markStack=markStack#entry=0xbee86804) at /usr/src/debug/qtdeclarative/5.12.8+gitAUTOINC+101799f8ac-r0/git/src/qml/memory/qv4mm.cpp:871
No locals.
#4 0xb695b678 in QV4::MemoryManager::mark (this=this#entry=0x1099c68) at /usr/src/debug/qtdeclarative/5.12.8+gitAUTOINC+101799f8ac-r0/git/src/qml/memory/qv4mm.cpp:912
markStack = {top = 0xaa8b7084, base = 0xaa8b7000, limit = 0xaaa37000, engine = 0x158efb8}
#5 0xb695cbb0 in QV4::MemoryManager::runGC (this=0x1099c68) at /usr/src/debug/qtdeclarative/5.12.8+gitAUTOINC+101799f8ac-r0/git/src/qml/memory/qv4mm.cpp:1047
gcBlocker = {varRef = #0x1099d2c, oldValue = false}
#6 0xb695e1e6 in QV4::MemoryManager::allocate (size=32, allocator=0x1099c70, this=0x1099c68) at ../../include/QtQml/5.12.8/QtQml/private/../../../../../../git/src/qml/memory/qv4mm_p.h:328
didGCRun = false
didGCRun = <optimized out>
m = <optimized out>
#7 QV4::MemoryManager::allocData (this=0x1099c68, size=32) at /usr/src/debug/qtdeclarative/5.12.8+gitAUTOINC+101799f8ac-r0/git/src/qml/memory/qv4mm.cpp:797
m = <optimized out>
#8 0xb695e284 in QV4::MemoryManager::allocObjectWithMemberData (this=this#entry=0x1099c68, vtable=vtable#entry=0xb6be4358 <QV4::Object::static_vtbl>, nMembers=<optimized out>) at /usr/src/debug/qtdeclarative/5.12.8+gitAUTOINC+101799f8ac-r0/git/src/qml/memory/qv4mm.cpp:809
size = <optimized out>
o = <optimized out>
#9 0xb6a690de in QV4::MemoryManager::allocateObject<QV4::Object> (ic=<optimized out>, this=<optimized out>) at ../../include/QtQml/5.12.8/QtQml/private/../../../../../../git/src/qml/jsruntime/qv4object_p.h:142
o = <optimized out>
o = <optimized out>
#10 QV4::MemoryManager::allocateObject<QV4::Object> (ic=0xaaab80a8, this=<optimized out>) at ../../include/QtQml/5.12.8/QtQml/private/../../../../../../git/src/qml/memory/qv4mm_p.h:201
No locals.
#11 QV4::MemoryManager::allocateObject<QV4::Object> (this=<optimized out>) at ../../include/QtQml/5.12.8/QtQml/private/../../../../../../git/src/qml/memory/qv4mm_p.h:211
scope = <optimized out>
ic = <optimized out>
scope = <optimized out>
ic = <optimized out>
#12 QV4::MemoryManager::allocate<QV4::Object> (this=<optimized out>) at ../../include/QtQml/5.12.8/QtQml/private/../../../../../../git/src/qml/memory/qv4mm_p.h:244
scope = <optimized out>
t = <optimized out>
scope = <optimized out>
t = <optimized out>
#13 QV4::ExecutionEngine::newObject (this=this#entry=0x158efb8) at /usr/src/debug/qtdeclarative/5.12.8+gitAUTOINC+101799f8ac-r0/git/src/qml/jsruntime/qv4engine.cpp:720
No locals.
#14 0xb69b8bf8 in QV4::ExecutionContext::createMutableBinding (this=<optimized out>, name=0xaaab8090, deletable=<optimized out>) at /usr/src/debug/qtdeclarative/5.12.8+gitAUTOINC+101799f8ac-r0/git/src/qml/jsruntime/qv4context.cpp:163
c = 0xaa5029c0
scope = {engine = 0x158efb8, mark = 0xaaab8098}
activation = {ptr = 0xaaab8098}
ctx = {ptr = 0xaaab80a0}
id = <optimized out>
desc = <optimized out>
attrs = {{m_all = 112 'p', {m_flags = 0 '\000', m_mask = 7 '\a'}, {m_type = 0 '\000', m_writable = 0 '\000', m_enumerable = 0 '\000', m_configurable = 0 '\000', type_set = 1 '\001', writable_set = 1 '\001', enumerable_set = 1 '\001', configurable_set = 0 '\000'}}}
#15 0xb6a74aae in QV4::Runtime::method_declareVar (engine=0x158efb8, deletable=<optimized out>, nameIndex=<optimized out>) at /usr/src/debug/qtdeclarative/5.12.8+gitAUTOINC+101799f8ac-r0/git/src/qml/jsruntime/qv4value_p.h:186
scope = {engine = 0x158efb8, mark = 0xaaab8090}
name = {ptr = 0xaaab8090}
#16 0xa9b6e47c in ?? ()
No symbol table info available.
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Unexpected sscanf Result

I have a sscanf statement that is behaving unexpectedly. This is somewhere around loop #8000 that it suddenly does this. This is the code, where str is a string parsed from a file:
char a1[6], a2[6], op[6], a3[6];
int success = sscanf(str.c_str(),"%*s %s %*s %s %s %s",a1, a2, op, a3);
And this is the gdb output on the problem line (str is "assign po012 = po011;"):
(gdb) print str
$9 = {<std::__1::__basic_string_common<true>> = {<No data fields>}, static __short_mask = 1, static __long_mask = 1,
__r_ = {<std::__1::__compressed_pair_elem<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, 0, false>> = {__value_ = {{__l = {__cap_ = 97, __size_ = 23, __data_ = 0x1003001d0 " assign po012 = po011;"}, __s = {{
__size_ = 97 'a', __lx = 97 'a'},
__data_ = "\000\000\000\000\000\000\000\027\000\000\000\000\000\000\000\320\001\060\000\001\000\000"}, __r = {__words = {
97, 23,
4298113488}}}}}, <std::__1::__compressed_pair_elem<std::__1::allocator<char>, 1, true>> = {<std::__1::allocator<char>> = {<No data fields>}, <No data fields>}, <No data fields>}, static npos = 18446744073709551615}
(gdb) n
81 string A1(a1);
(gdb) print a1
$10 = "\000o012"
(gdb) print a2
$13 = "po011;"
a2 has the expected value, but what is happening to a1 in just this one case?
Your arrays have length six:
char a1[6], a2[6], op[6], a3[6];
Yet, sscanf causes "po011;" to be written in a2, and this requires seven characters, since sscanf will add the null terminator. Hence, sscanf causes undefined behavior.
Pragmatically, in your implementation the null terminator was added to the beginning of a1, which changed from the intended "po012" to "\000o012" (the initial p was overwritten). It looks like your implementation chose to store a1 right after a2, so overflowing a2 overwrote a1. This is one of the things that can happen when undefined behavior is triggered.

What happens to the string data when std::string objects are passed to functions?

I've noticed something I don't understand happening to the string arguments to functions.
I've written this little test program:
#include <string>
#include <iostream>
using namespace std;
void foo(string str) {
cout << str << endl;
}
int main(int argc, char** argv) {
string hello = "hello";
foo(hello);
}
I compile it like this:
$ g++ -o string_test -g -O0 string_test.cpp
Under g++ 4.2.1 on Mac OSX 10.6, str inside foo() looks the same as it does as hello outside foo():
12 foo(hello);
(gdb) p hello
$1 = {
static npos = 18446744073709551615,
_M_dataplus = {
<std::allocator<char>> = {
<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
members of std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider:
_M_p = 0x100100098 "hello"
}
}
(gdb) s
foo (str=#0x7fff5fbfd350) at string_test.cpp:7
7 cout << str << endl;
(gdb) p str
$2 = (string &) #0x7fff5fbfd350: {
static npos = 18446744073709551615,
_M_dataplus = {
<std::allocator<char>> = {
<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
members of std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider:
_M_p = 0x100100098 "hello"
}
}
Under g++ 4.3.3 on Ubuntu, however, it doesn't:
12 foo(hello);
(gdb) p hello
$1 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603028 "hello"}}
(gdb) s
foo (str={static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fff5999e530 "(0`"}}) at string_test.cpp:7
7 cout << str << endl;
(gdb) p str
$2 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fff5999e530 "(0`"}}
(gdb) p str->_M_dataplus->_M_p
$3 = 0x7fff5999e530 "(0`"
So, what's happening to the value of the string when it is passed to this function? And why the difference between the two compilers?
On my compiler foo() is inlined, so there is only one hello. Perhaps that is what is happening for you too.
What a program looks like in a debugger is not part of the language standard. Only the visible result, like actually printing "Hello", is.