在gdb中获取打印表示的输出,并用gdb的printf作为字符串使用它? [英] Getting the output of print representation in gdb, and using it as a string with gdb's printf?
问题描述
在GDB中使用 print
和 printf
命令有一个区别: print
如果参数是一个对象,可能会打印相关字段,而 printf
严格要求格式说明符和C风格字符串。
There is a difference in using print
and printf
commands in GDB: print
may print related fields if the argument is an object, while printf
strictly expects format specifiers and C-style strings.
我想要做的是获取 gdb
print $ c $的输出c>表达式,并将其用作带有
%s
格式说明符的字符串数据。通常情况下,这是行不通的 - 使用 test.cpp
程序:
What I'd like to do, is to "get" the output of a gdb
print
expression, and use it as a string data with a %s
format specifier. Usually, that doesn't work - with this test.cpp
program:
// g++ --std=c++11 -g test.cpp -o test.exe
#include <iostream>
#include <set>
std::string aa; // just to have reference to std::string
int main()
{
std::set<std::string> my_set;
my_set.insert("AA");
my_set.insert("BB");
std::cout << "Hello World!" << std::endl;
return 0;
}
我可以得到如下输出:
I can get output like this:
$ gdb --args ./test.exe
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
...
Breakpoint 1, main () at test.cpp:13
13 std::cout << "Hello World!" << std::endl;
(gdb) p my_set
$1 = std::set with 2 elements = {[0] = "AA", [1] = "BB"}
(gdb) p *my_set
No symbol "operator*" in current context.
(gdb) p my_set->begin()
Cannot resolve method std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::begin to any overloaded instance
...但我不能只使用 my_set
作为 printf
的参数,因为会有一个char数组:
... but I cannot just use my_set
as argument of printf
, since there a char array would be expected:
(gdb) printf "it is: '%s'\n", my_set
it is: 'Value can't be converted to integer.
那么,是否有可能以某种方式获得打印对象的表示作为一个字符串,用它作为参数
printf
?假设伪代码函数 print_repr()
,我想实现这一点:
So, is it possible to somehow obtain the representation of an object of print
as a string, to use it as an argument of printf
? Assuming pseudocode function print_repr()
, I'd like to achieve this:
(gdb) printf "it is: '%s'\n", print_repr(my_set)
it is: '= std::set with 2 elements = {[0] = "AA", [1] = "BB"}'
...并且也希望相同的功能可用于错误,说:
... and also would like the same to function for errors, say:
(gdb) printf "it is: '%s'\n", print_repr(*my_set)
it is: 'No symbol "operator*" in current context.'
这可能吗?
推荐答案
我刚刚使用@TomTromey的指针尝试了这个,但它并不完全无关紧要,所以我发布了这是一个答案,在gdb 7.7.1上测试过。首先,我将它添加到我的〜/ .gdbinit
文件中:
I just tried this using @TomTromey's pointers, but it wasn't exactly trivial, so I'm posting this as an answer, tested on gdb 7.7.1. First, I added this to my ~/.gdbinit
file:
python
# https://sourceware.org/gdb/onlinedocs/gdb/Python-API.html#Python-API
# https://sourceware.org/gdb/onlinedocs/gdb/Functions-In-Python.html
class Greet (gdb.Function):
"""Return string to greet someone.
Takes a name as argument."""
def __init__ (self):
super (Greet, self).__init__ ("greet")
def invoke (self, name):
return "Hello, %s!" % name.string ()
Greet() # instantiate; then call in gdb: p $greet("myname")
#(gdb) python gdb.execute("p 22")
#$2 = 22
class Strp (gdb.Function):
"""Get a representation of gdb's printout as string
Argument: the gdb command as string."""
def __init__ (self):
super (Strp, self).__init__ ("strp")
def invoke (self, incmd):
incmds = str(incmd)
#print("is",incmds)
# strip quotes
if (incmds[0] == incmds[-1]) and incmds.startswith(("'", '"')):
incmds = incmds[1:-1]
rets=""
try:
rets += gdb.execute(incmds, from_tty=True, to_string=True)
except Exception as e:
rets += "Exception: {0}".format(e)
#print("ret",ret)
return rets
Strp() # instantiate; then call in gdb: p $strp("p 22")
# quotes end up in arg string, so by default getting Python Exception <class 'gdb.error'> Undefined command: "". Try "help".: ... but then, if call WITHOUT quotes p $strp(p aa), gdb may interpret "p" as symbol (which doesn't exist) before it is sent as arg to python; therefore, use quotes, then strip them
end
然后,我可以在 gdb
:
(gdb) p $strp("x 22")
$1 = "Exception: Cannot access memory at address 0x16"
(gdb) p $strp("p 22")
$3 = "$2 = 22\n"
(gdb) p $strp("p aa")
$4 = "Exception: No symbol \"aa\" in current context."
(gdb) printf "%s\n", $strp("p 22")
You can't do that without a process to debug.
因此,常规 gdb
p
rint不需要一个进程,但是 printf
不会 - 所以在设置断点之后,并且 r
在 gdb
中统一程序/进程,最后可以同时使用Python函数和 printf
在提示符下:
So, the regular gdb
p
rint does not need a process, however printf
does - so after setting a breakpoint, and r
unning the program/process in gdb
, finally one can use both the Python function and printf
at the prompt:
Breakpoint 1, main () at /...:17
17 int main( ){
(gdb) printf "%s\n", "aa"
aa
(gdb) printf "%s\n", $strp("p 22")
$12 = 22
(gdb) printf "%s\n", $strp("x 22")
Exception: Cannot access memory at address 0x16
(gdb) printf "%s\n", $strp("p aa")
Exception: No symbol "aa" in current context.
(gdb) printf "%s -- %s\n", $strp("p aa"), $strp("p 22")
Exception: No symbol "aa" in current context. -- $13 = 22
这篇关于在gdb中获取打印表示的输出,并用gdb的printf作为字符串使用它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!