From e24d7dea7194f48c7e623f0a34adb2e4bb534cb8 Mon Sep 17 00:00:00 2001 From: Vahagn Khachatryan Date: Thu, 6 Nov 2014 19:04:08 +0400 Subject: [PATCH] .gdbinit and STL container printers are added. --- gdb/gdbinit | 18 ++ gdb/print_stl | 680 +++++++++++++++++++++++++++++++++++++++++ gdb/print_stl_test.cpp | 47 +++ 3 files changed, 745 insertions(+) create mode 100644 gdb/gdbinit create mode 100644 gdb/print_stl create mode 100644 gdb/print_stl_test.cpp diff --git a/gdb/gdbinit b/gdb/gdbinit new file mode 100644 index 0000000..cd7c483 --- /dev/null +++ b/gdb/gdbinit @@ -0,0 +1,18 @@ +set disassembly-flavor intel +set confirm off +#set follow-fork-mode child +#set detach-on-fork off + +# +# C++ related beautifiers +# +set print pretty on +set print object on +#set print static-members on +set print vtbl on +set print demangle on +set demangle-style gnu-v3 +set print sevenbit-strings off + +source ~/devel/scripts/gdb/print_stl + diff --git a/gdb/print_stl b/gdb/print_stl new file mode 100644 index 0000000..76da9b6 --- /dev/null +++ b/gdb/print_stl @@ -0,0 +1,680 @@ +# +# STL GDB evaluators/views/utilities - 1.03 +# +# The new GDB commands: +# are entirely non instrumental +# do not depend on any "inline"(s) - e.g. size(), [], etc +# are extremely tolerant to debugger settings +# +# This file should be "included" in .gdbinit as following: +# source stl-views.gdb or just paste it into your .gdbinit file +# +# The following STL containers are currently supported: +# +# std::vector -- via pvector command +# std::list -- via plist or plist_member command +# std::map -- via pmap or pmap_member command +# std::multimap -- via pmap or pmap_member command +# std::set -- via pset command +# std::multiset -- via pset command +# std::deque -- via pdequeue command +# std::stack -- via pstack command +# std::queue -- via pqueue command +# std::priority_queue -- via ppqueue command +# std::bitset -- via pbitset command +# std::string -- via pstring command +# std::widestring -- via pwstring command +# +# The end of this file contains (optional) C++ beautifiers +# Make sure your debugger supports $argc +# +# Simple GDB Macros writen by Dan Marinescu (H-PhD) - License GPL +# Inspired by intial work of Tom Malnar, +# Tony Novac (PhD) / Cornell / Stanford, +# Gilad Mishne (PhD) and Many Many Others. +# Contact: dan_c_marinescu@yahoo.com (Subject: STL) +# +# Modified to work with g++ 4.3 by Anders Elton +# Also added _member functions, that instead of printing the entire class in map, prints a member. + + + +# +# std::vector<> +# +define pvector + if $argc == 0 + help pvector + else + set $size = $arg0._M_impl._M_finish - $arg0._M_impl._M_start + set $capacity = $arg0._M_impl._M_end_of_storage - $arg0._M_impl._M_start + set $size_max = $size - 1 + end + if $argc == 1 + set $i = 0 + while $i < $size + printf "elem[%u]: ", $i + p *($arg0._M_impl._M_start + $i) + set $i++ + end + end + if $argc == 2 + set $idx = $arg1 + if $idx < 0 || $idx > $size_max + printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max + else + printf "elem[%u]: ", $idx + p *($arg0._M_impl._M_start + $idx) + end + end + if $argc == 3 + set $start_idx = $arg1 + set $stop_idx = $arg2 + if $start_idx > $stop_idx + set $tmp_idx = $start_idx + set $start_idx = $stop_idx + set $stop_idx = $tmp_idx + end + if $start_idx < 0 || $stop_idx < 0 || $start_idx > $size_max || $stop_idx > $size_max + printf "idx1, idx2 are not in acceptable range: [0..%u].\n", $size_max + else + set $i = $start_idx + while $i <= $stop_idx + printf "elem[%u]: ", $i + p *($arg0._M_impl._M_start + $i) + set $i++ + end + end + end + if $argc > 0 + printf "Vector size = %u\n", $size + printf "Vector capacity = %u\n", $capacity + printf "Element " + whatis $arg0._M_impl._M_start + end +end +document pvector + Prints std::vector information. + Syntax: pvector + Note: idx, idx1 and idx2 must be in acceptable range [0...size()-1]. + Examples: + pvector v - Prints vector content, size, capacity and T typedef + pvector v 0 - Prints element[idx] from vector + pvector v 1 2 - Prints elements in range [idx1..idx2] from vector +end + +# +# std::list<> +# +define plist + if $argc == 0 + help plist + else + set $head = &$arg0._M_impl._M_node + set $current = $arg0._M_impl._M_node._M_next + set $size = 0 + while $current != $head + if $argc == 2 + printf "elem[%u]: ", $size + p *($arg1*)($current + 1) + end + if $argc == 3 + if $size == $arg2 + printf "elem[%u]: ", $size + p *($arg1*)($current + 1) + end + end + set $current = $current._M_next + set $size++ + end + printf "List size = %u \n", $size + if $argc == 1 + printf "List " + whatis $arg0 + printf "Use plist to see the elements in the list.\n" + end + end +end + +document plist + Prints std::list information. + Syntax: plist : Prints list size, if T defined all elements or just element at idx + Examples: + plist l - prints list size and definition + plist l int - prints all elements and list size + plist l int 2 - prints the third element in the list (if exists) and list size +end + +define plist_member + if $argc == 0 + help plist_member + else + set $head = &$arg0._M_impl._M_node + set $current = $arg0._M_impl._M_node._M_next + set $size = 0 + while $current != $head + if $argc == 3 + printf "elem[%u]: ", $size + p (*($arg1*)($current + 1)).$arg2 + end + if $argc == 4 + if $size == $arg3 + printf "elem[%u]: ", $size + p (*($arg1*)($current + 1)).$arg2 + end + end + set $current = $current._M_next + set $size++ + end + printf "List size = %u \n", $size + if $argc == 1 + printf "List " + whatis $arg0 + printf "Use plist_member to see the elements in the list.\n" + end + end +end + +document plist_member + Prints std::list information. + Syntax: plist : Prints list size, if T defined all elements or just element at idx + Examples: + plist_member l int member - prints all elements and list size + plist_member l int member 2 - prints the third element in the list (if exists) and list size +end + + +# +# std::map and std::multimap +# + +define pmap + if $argc == 0 + help pmap + else + set $tree = $arg0 + set $i = 0 + set $node = $tree._M_t._M_impl._M_header._M_left + set $end = $tree._M_t._M_impl._M_header + set $tree_size = $tree._M_t._M_impl._M_node_count + if $argc == 1 + printf "Map " + whatis $tree + printf "Use pmap to see the elements in the map.\n" + end + if $argc == 3 + while $i < $tree_size + set $value = (void *)($node + 1) + printf "elem[%u].left: ", $i + p *($arg1*)$value + set $value = $value + sizeof($arg1) + printf "elem[%u].right: ", $i + p *($arg2*)$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++ + end + end + if $argc == 4 + set $idx = $arg3 + set $ElementsFound = 0 + while $i < $tree_size + set $value = (void *)($node + 1) + if *($arg1*)$value == $idx + printf "elem[%u].left: ", $i + p *($arg1*)$value + set $value = $value + sizeof($arg1) + printf "elem[%u].right: ", $i + p *($arg2*)$value + set $ElementsFound++ + end + 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++ + end + printf "Number of elements found = %u\n", $ElementsFound + end + if $argc == 5 + set $idx1 = $arg3 + set $idx2 = $arg4 + set $ElementsFound = 0 + while $i < $tree_size + set $value = (void *)($node + 1) + set $valueLeft = *($arg1*)$value + set $valueRight = *($arg2*)($value + sizeof($arg1)) + if $valueLeft == $idx1 && $valueRight == $idx2 + printf "elem[%u].left: ", $i + p $valueLeft + printf "elem[%u].right: ", $i + p $valueRight + set $ElementsFound++ + end + 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++ + end + printf "Number of elements found = %u\n", $ElementsFound + end + printf "Map size = %u\n", $tree_size + end +end + +document pmap + Prints std::map or std::multimap information. Works for std::multimap as well. + Syntax: pmap : Prints map size, if T defined all elements or just element(s) with val(s) + Examples: + pmap m - prints map size and definition + pmap m int int - prints all elements and map size + pmap m int int 20 - prints the element(s) with left-value = 20 (if any) and map size + pmap m int int 20 200 - prints the element(s) with left-value = 20 and right-value = 200 (if any) and map size +end + + +define pmap_member + if $argc == 0 + help pmap_member + else + set $tree = $arg0 + set $i = 0 + set $node = $tree._M_t._M_impl._M_header._M_left + set $end = $tree._M_t._M_impl._M_header + set $tree_size = $tree._M_t._M_impl._M_node_count + if $argc == 1 + printf "Map " + whatis $tree + printf "Use pmap to see the elements in the map.\n" + end + if $argc == 5 + while $i < $tree_size + set $value = (void *)($node + 1) + printf "elem[%u].left: ", $i + p (*($arg1*)$value).$arg2 + set $value = $value + sizeof($arg1) + printf "elem[%u].right: ", $i + p (*($arg3*)$value).$arg4 + 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++ + end + end + if $argc == 6 + set $idx = $arg5 + set $ElementsFound = 0 + while $i < $tree_size + set $value = (void *)($node + 1) + if *($arg1*)$value == $idx + printf "elem[%u].left: ", $i + p (*($arg1*)$value).$arg2 + set $value = $value + sizeof($arg1) + printf "elem[%u].right: ", $i + p (*($arg3*)$value).$arg4 + set $ElementsFound++ + end + 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++ + end + printf "Number of elements found = %u\n", $ElementsFound + end + printf "Map size = %u\n", $tree_size + end +end + +document pmap_member + Prints std::map or std::multimap information. Works for std::multimap as well. + Syntax: pmap : Prints map size, if T defined all elements or just element(s) with val(s) + Examples: + pmap_member m class1 member1 class2 member2 - prints class1.member1 : class2.member2 + pmap_member m class1 member1 class2 member2 lvalue - prints class1.member1 : class2.member2 where class1 == lvalue +end + + +# +# std::set and std::multiset +# + +define pset + if $argc == 0 + help pset + else + set $tree = $arg0 + set $i = 0 + set $node = $tree._M_t._M_impl._M_header._M_left + set $end = $tree._M_t._M_impl._M_header + set $tree_size = $tree._M_t._M_impl._M_node_count + if $argc == 1 + printf "Set " + whatis $tree + printf "Use pset to see the elements in the set.\n" + end + if $argc == 2 + while $i < $tree_size + set $value = (void *)($node + 1) + printf "elem[%u]: ", $i + p *($arg1*)$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++ + end + end + if $argc == 3 + set $idx = $arg2 + set $ElementsFound = 0 + while $i < $tree_size + set $value = (void *)($node + 1) + if *($arg1*)$value == $idx + printf "elem[%u]: ", $i + p *($arg1*)$value + set $ElementsFound++ + end + 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++ + end + printf "Number of elements found = %u\n", $ElementsFound + end + printf "Set size = %u\n", $tree_size + end +end + +document pset + Prints std::set or std::multiset information. Works for std::multiset as well. + Syntax: pset : Prints set size, if T defined all elements or just element(s) having val + Examples: + pset s - prints set size and definition + pset s int - prints all elements and the size of s + pset s int 20 - prints the element(s) with value = 20 (if any) and the size of s +end + + + +# +# std::dequeue +# + +define pdequeue + if $argc == 0 + help pdequeue + else + set $size = 0 + set $start_cur = $arg0._M_impl._M_start._M_cur + set $start_last = $arg0._M_impl._M_start._M_last + set $start_stop = $start_last + while $start_cur != $start_stop + p *$start_cur + set $start_cur++ + set $size++ + end + set $finish_first = $arg0._M_impl._M_finish._M_first + set $finish_cur = $arg0._M_impl._M_finish._M_cur + set $finish_last = $arg0._M_impl._M_finish._M_last + if $finish_cur < $finish_last + set $finish_stop = $finish_cur + else + set $finish_stop = $finish_last + end + while $finish_first != $finish_stop + p *$finish_first + set $finish_first++ + set $size++ + end + printf "Dequeue size = %u\n", $size + end +end + +document pdequeue + Prints std::dequeue information. + Syntax: pdequeue : Prints dequeue size, if T defined all elements + Deque elements are listed "left to right" (left-most stands for front and right-most stands for back) + Example: + pdequeue d - prints all elements and size of d +end + + + +# +# std::stack +# + +define pstack + if $argc == 0 + help pstack + else + set $start_cur = $arg0.c._M_impl._M_start._M_cur + set $finish_cur = $arg0.c._M_impl._M_finish._M_cur + set $size = $finish_cur - $start_cur + set $i = $size - 1 + while $i >= 0 + p *($start_cur + $i) + set $i-- + end + printf "Stack size = %u\n", $size + end +end + +document pstack + Prints std::stack information. + Syntax: pstack : Prints all elements and size of the stack + Stack elements are listed "top to buttom" (top-most element is the first to come on pop) + Example: + pstack s - prints all elements and the size of s +end + + + +# +# std::queue +# + +define pqueue + if $argc == 0 + help pqueue + else + set $start_cur = $arg0.c._M_impl._M_start._M_cur + set $finish_cur = $arg0.c._M_impl._M_finish._M_cur + set $size = $finish_cur - $start_cur + set $i = 0 + while $i < $size + p *($start_cur + $i) + set $i++ + end + printf "Queue size = %u\n", $size + end +end + +document pqueue + Prints std::queue information. + Syntax: pqueue : Prints all elements and the size of the queue + Queue elements are listed "top to bottom" (top-most element is the first to come on pop) + Example: + pqueue q - prints all elements and the size of q +end + + + +# +# std::priority_queue +# + +define ppqueue + if $argc == 0 + help ppqueue + else + set $size = $arg0.c._M_impl._M_finish - $arg0.c._M_impl._M_start + set $capacity = $arg0.c._M_impl._M_end_of_storage - $arg0.c._M_impl._M_start + set $i = $size - 1 + while $i >= 0 + p *($arg0.c._M_impl._M_start + $i) + set $i-- + end + printf "Priority queue size = %u\n", $size + printf "Priority queue capacity = %u\n", $capacity + end +end + +document ppqueue + Prints std::priority_queue information. + Syntax: ppqueue : Prints all elements, size and capacity of the priority_queue + Priority_queue elements are listed "top to buttom" (top-most element is the first to come on pop) + Example: + ppqueue pq - prints all elements, size and capacity of pq +end + + + +# +# std::bitset +# + +define pbitset + if $argc == 0 + help pbitset + else + p /t $arg0._M_w + end +end + +document pbitset + Prints std::bitset information. + Syntax: pbitset : Prints all bits in bitset + Example: + pbitset b - prints all bits in b +end + + + +# +# std::string +# + +define pstring + if $argc == 0 + help pstring + else + printf "String \t\t\t= \"%s\"\n", $arg0._M_data() + printf "String size/length \t= %u\n", $arg0._M_rep()._M_length + printf "String capacity \t= %u\n", $arg0._M_rep()._M_capacity + printf "String ref-count \t= %d\n", $arg0._M_rep()._M_refcount + end +end + +document pstring + Prints std::string information. + Syntax: pstring + Example: + pstring s - Prints content, size/length, capacity and ref-count of string s +end + +# +# std::wstring +# + +define pwstring + if $argc == 0 + help pwstring + else + call printf("WString \t\t= \"%ls\"\n", $arg0._M_data()) + printf "WString size/length \t= %u\n", $arg0._M_rep()._M_length + printf "WString capacity \t= %u\n", $arg0._M_rep()._M_capacity + printf "WString ref-count \t= %d\n", $arg0._M_rep()._M_refcount + end +end + +document pwstring + Prints std::wstring information. + Syntax: pwstring + Example: + pwstring s - Prints content, size/length, capacity and ref-count of wstring s +end + diff --git a/gdb/print_stl_test.cpp b/gdb/print_stl_test.cpp new file mode 100644 index 0000000..5b5aeb1 --- /dev/null +++ b/gdb/print_stl_test.cpp @@ -0,0 +1,47 @@ +//VIM: let g:lcppflags="-g --std=c++0x" +// +#include +#include +#include +#include +#include +#include + +int main() +{ + std::vector v; + v.push_back(10); + v.push_back(11); + v.push_back(12); + v.push_back(13); + + std::vector> v2; + v2.push_back(std::make_pair(23,34)); + v2.push_back(std::make_pair(3,4)); + v2.push_back(std::make_pair(423,534)); + + std::list> l; + l.push_back(std::make_pair(23,34)); + l.push_back(std::make_pair(3,4)); + l.push_back(std::make_pair(423,534)); + + std::deque> q; + q.push_back(std::make_pair(23,34)); + q.push_back(std::make_pair(3,4)); + q.push_back(std::make_pair(423,534)); + + std::map m; + m.insert(std::make_pair(23,34)); + m.insert(std::make_pair(3,4)); + m.insert(std::make_pair(423,534)); + + std::set> s; + s.insert(std::make_pair(23,34)); + s.insert(std::make_pair(3,4)); + s.insert(std::make_pair(423,534)); + + std::string str = "This is a string."; + +break_here: + return 0; +}