In .gdbinit I call to function
call open("tmp/test",1)
Then I got return value
$15 = 1
I want to use $15 to the next operation.
How can I got this var to the .gdbinit next line ?
You can simply assign the return value to a variable with a name of your choosing:
(gdb) call $ret = open("tmp/test", 1)
(gdb) print $ret
-1
Related
By default, using p variable-name will display $num = variable-value, $num is the value history, but it there a way to print the variable name along with the variable value like $num = variable-name = variable-value?
I want this since I use
define p
set $i = 0
while $i < $argc
eval "print $arg%d", $i
set $i = $i + 1
end
end
in my ~/.gdbinit, to redefine p command so I can use p var1 var2 var3... to print multiple variables at once, but the print command only output $num = variable-value, and I don't know what the exact variable is in the output, the other situation is when I print the value history using just p $num, it is not that readable, I don't know the exact variable name.
NOTE: the variable may be int/char/pointer/array/vector/...
A solution could be to first add to the display list the wanted variables and then to display all of them together. Note that, it is needed to free the display list before with undisplay, otherwise it also prints the variables of the previous executions.
define p
set confirm off
eval "undisplay"
set confirm on
set $i = 0
while $i < $argc
eval "display $arg%d", $i
set $i = $i + 1
end
display
end
The undisplay evaluation is enclosed between set confirm off/on to suppress the following message:
[answered Y; input not from terminal]
If you have already set the confirm off option in your ~/gdbinit file, you will need to remove these two lines.
Edit: Honestly, I came to know about the display command finding a solution for this question. Although this answer might be useful to print multiple variables with their respective names, after several days using display in my workflow, I discourage to use this answer since I have come to the conclusion that display itself fits better at least my needs (printing multiple variables at every stop). Here the official doc:
If you find that you want to print the value of an expression frequently (to see how it changes), you might want to add it to the automatic display list so that GDB prints its value each time your program stops. Each expression added to the list is given a number to identify it; to remove an expression from the list, you specify that number. The automatic display looks like this:
2: foo = 38
3: bar[5] = (struct hack *) 0x3804
Basically, I have started using the command like this: I add a variable with display $var to the list of variables, and every time a breakpoint is reached the listed variables are automatically printed. It makes sense to have a feature like this in gdb. Thanks #CodyChan for the motivation.
In a nutshell, we want to output
$num = variable-name = variable-value
instead of
$num = variable-value
As far as I can tell, gdb adds to the value history in only three places: the print command, the call command, and the history-append! Scheme function. Since my Scheme is rusty, we'll need to use the CLI or Python to run print and modify its output.
Using the CLI
define pp
set $i = 0
while $i < $argc
eval "pipe print $arg%d | awk -v name='$arg%d' '{ if (NR == 1 && $2 == \"=\") { $2 = \"= \" name \" =\" }; print }'", $i, $i
set $i++
end
end
Pipe is new in gdb 10.
That awk command is, after unescaping,
awk -v name='$arg%d' '{ if (NR == 1 && $2 == "=") { $2 = "= " name " =" }; print }'
which changes the = (second field) in $num = variable-value to = variable-name = . If gdb's print command outputs more than one line, the NR == 1 in the awk command makes sure the substitution is only done on the first line.
Security note: gdb's pipe command appears to parse the shell_command into tokens and uses execve to run it, rather than passing it to an actual shell. This prevents some code injection attacks (if, for instance, the $arg%d in name='$arg%d' contains single quotes), but you should be careful of running any shell command comprised of text you haven't vetted.
Using Python
class PP(gdb.Command):
"""print value history index, name, and value of each arg"""
def __init__(self):
super(PP, self).__init__("pp", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION)
def invoke(self, argstr, from_tty):
for arg in gdb.string_to_argv(argstr):
line = gdb.execute("print " + arg, from_tty=False, to_string=True)
line = line.replace("=", "= " + arg + " =", 1)
gdb.write(line)
PP()
Here, we're using a more sed-like approach, using string.replace.
Sample session:
(gdb) set args a b c
(gdb) start
Starting program: /home/mp/argprint a b c
Temporary breakpoint 2, main (argc=4, argv=0x7ffffffee278) at argprint.c:4
4 for(int i=0; i < argc; i++) {
(gdb) pp i argc argv argv[0]#argc
$1 = i = 0
$2 = argc = 4
$3 = argv = (char **) 0x7ffffffee278
$4 = argv[0]#argc = {0x7ffffffee49f "/home/mp/argprint", 0x7ffffffee4b1 "a", 0x7ffffffee4b3 "b", 0x7ffffffee4b5 "c"}
I'm using gdb with the -x parameter in order to debug without having to interactively continue at each breakpoint.
[root#StackOverflow.com] $ cat gdb_cmds_01
b SomeSourceFile.cpp:123
commands
bt
cont
end
I'm then attaching to a process that uses SomeSourceFile.cpp in it's execution:
[root#StackOverflow.com] $ gdb -p 'pidof SomeRunningProgram' -x gdb_cmds_01
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
...
<GDB outputs a set S of backtraces as instructed by gdb_cmds_01>
Now, Let SomeSourceFile.cpp:123 contain a line like:
if (foo(person, &place, *time) == "Alice") { ... <do stuff > ... }
And then Suppose I want to break on SomeSourceFile:123 only if the return of foo(...) is not equal to "Alice".
Based on:
How to inspect the return value of a function in GDB?, I know that gdb can inspect the return value of a function.
And https://sourceware.org/gdb/onlinedocs/gdb/Break-Commands.html tells me that I can inspect the value of a variable non-interactively:
<...>
For example, here is how you could use breakpoint commands to print the value of x at entry to foo whenever x is positive.
break foo if x>0
commands
silent
printf "x is %d\n",x
cont
end
<...>
I have tried something like:
[root#StackOverflow.com] $ cat gdb_cmds_01
b SomeSourceFile.cpp:123 if foo(person, &place, *time) != "Alice"
commands
bt
cont
end
But GDB spits out:
gdb_cmds_01:1: Error in sourced command file:
No symbol "place" in current context.
Can this be worked around?
In order to break on SomeSourceFile.cpp:123 only when foo(...) != "Alice", can I also inspect the return value of a function non-interactively?
In other words, I want to see only a subset R of the set of backtraces S such that for all backtraces b in R, the return of foo(...) is always unequal to "Alice".
Suppose I want to break on SomeSourceFile:123 only if the return of foo(...) is not equal to "Alice".
This fairly easy to do if you go to the lower (assembly level), and if the code is built without optimization.
It is also trivial to do if you can modify the source like so:
if (foo(...) == "Alice") { ...
} else {
int x = 0; if (x) abort(); // break here
}
Now you can simply set breakpoint on line 125, and you are done.
So how can you do this without modifying the source?
You must understand that the compiler invokes some bool operator==(), compares the return to true or false, and conditionally jumps around the body of if when the condition is false.
The (gdb) info line 123 will give you range of instructions that were produced for this source line.
Disassembling that range of instructions will allow you to locate the call to operator==, and show you the instruction that compares EAX (JE or JNE) with 0 or 1.
You can then set the breakpoint on the conditional jump instruction, and use $EAX (or $RAX for 64-bit code) is the condition on that breakpoint.
I have a file named testing.cpp:
#include <iostream>
#include <string>
struct Foo {
std::string name;
};
int main() {
Foo* foo = new Foo;
foo->name = "hello";
std::cout << foo->name << "\n";
return 0;
}
I compiled it to a.out, and start gdb using gdb a.out.
GNU gdb (Debian 7.10-1.1) 7.10
...
Reading symbols from a.out...done.
(gdb)
I break at line 12 (std::cout << foo->name << "\n";), and run:
(gdb) break 12
Breakpoint 1 at 0x400990: file testing.cpp, line 12.
(gdb) run
Starting program: ...
Breakpoint 1, main () at testing.cpp:12
12 std::cout << foo->name << "\n";
(gdb)
It can print foo->name and foo->name.c_str():
(gdb) print foo->name
$1 = "hello"
(gdb) print foo->name.c_str()
$2 = 0x613c30 "hello"
It can print boolean expression with foo->name.c_str() in the first clause:
(gdb) print foo->name.c_str() && 1
$3 = true
But it can't when I put foo->name.c_str() in second clause:
(gdb) print 1 && foo->name.c_str()
Attempt to take address of value not located in memory.
(gdb)
Is this a bug?
Edit 1:
Use Case
I was trying to use break ... if ... to break at some point if some strings have certain values. E.g.
(gdb) break 14 if foo->name.size() == 5 && $_streq(foo->name.c_str(), "house")
Breakpoint 2 at 0x400aba: file testing.cpp, line 14
(gdb)
When I continue, gdb show the error message and break at line 14 (return 0;) even though foo->name is "hello" but not "house".
(gdb) continue
Continuing.
hello
Error in testing breakpoint condition:
Attempt to take address of value not located in memory.
Breakpoint 2, main () at testing.cpp:14
14 return 0;
(gdb)
Currently a workaround is access data member of std::string directly:
(gdb) break 14 if foo->name.size() == 5 && \
$_streq(foo->name._M_dataplus._M_p, "house")
Some Observations
Is it because my foo is pointer?
Nope. I tried to use Foo foo; instead of Foo* foo = new Foo;. Problem remains.
Does this problem apply for std::string variable created in main(), oppose to as a data member of some object?
Nope. Seems like it only applies for std::string as a data member. Code below works:
(gdb) list 4,8
4 int main() {
5 std::string name("hello");
6 std::cout << name << "\n";
7 return 0;
8 }
(gdb) break 6
Breakpoint 1 at 0x400a93: file testing.cpp, line 6
(gdb) run
Starting program: ...
Breakpoint 1, main() at testing.cpp:6
6 std::cout << name << "\n";
(gdb) print 1 && name.c_str()
$1 = true
Does this problem unique to c_str() only? How about other function?
No, this problem is not unique to c_str(). It is not even unique to std::string. Seems like it happens when we call member function of object inside another object, i.e. foo.bar.func().
What I want is this :
(gdb) define mynext
Redefine command "mynext"? (y or n) y
Type commands for definition of "mynext".
End with a line saying just "end".
>print "------"
>print Location:
>where
>print "-------------"
>print Code:
>list
>print "---------------------"
>print Next:
>next
>end
This is what outputs is:
$1 = "-----"
....
I expect:
-----
....
I used call printf("opopo") also, but It print the return value of "opopo" which is 5. Just like this:$4 = 5
My question is: how can I print something without this format which is :$[num]=[value].
As you found, print puts the printed value into the value history. gdb provides two different ways to avoid this.
One is printf. This works somewhat like the C function, but is a gdb command. Use it like:
(gdb) printf "whatever you like\n"
whatever you like
(gdb)
Another is output. This is a bit like the print command, but does not enter the value into the value history.
(gdb) output 5
5(gdb)
You can see from this that output also doesn't emit a trailing newline. You would have to add that yourself.
def check_answer(self, currentscore):
self.user_entry = self.user_entry.get_text()
if self.user_entry == self.books:
self.current += 1
self.total += 1
self.currentscore = self.current
print "right"
else:
print "wrong"
print self.currentscore
print self.total
When i run it and i put text a second time is says File "C:\Python27\guessing.py", line 16, in check_answer
self.user_entry = self.user_entry.get_text()
AttributeError: 'str' object has no attribute 'get_text'
Could someone explain it to me. Why it to me why it only works once. and also why doesn't the program execute the if statement. It only says wrong.
self.books = 'hello'
You overwrite the variable holding the reference to the text box with its contents. So when check_answer runs for the first time, self.user_entry is your text box, and you can call its method get_text() to retrieve the text entered by the user. Unfortunately, you assign this text to the same variable (self.user_entry =) - so you loose the reference to the text box. After the first call, self.user_entry is a string (instance of str class) retrieved at the first call.
Use a different variable name, like this:
def check_answer(self, currentscore):
self.user_entry_text = self.user_entry.get_text()
if self.user_entry_text == self.books:
self.current += 1
self.total += 1
self.currentscore = self.current
print "right"
else:
print "wrong"
print self.currentscore
print self.total
Also, possibly it doesn't have to be class's field, so you can also skip the self. part. In such case you could use the same name (user_entry), but for sake of readability it's better to call a variable with a name that says precisely what the variable holds:
user_entry_text = self.user_entry.get_text()
if user_entry_text == self.books: