why is the syntax for "condition" and "break" different in gdb? - debugging

I seem to be having an issue with gdb. Let's say I create a conditional breakpoint in a loop over i with the command
break file.cpp:line_no if i==120
everything good, it creates breakpoint 3 and the code breaks when i==120. Now I'm getting a problem at i==495, and I want to re-use the same breakpoint, so I use:
condition 3 if i==495
Well, there I get a "syntax error in expression near `if i==495' So I try:
condition 3 i==495
No more error, and the info for the breakpoint looks promising:
3 breakpoint keep y <MULTIPLE>
stop only if i==495
But it doesn't stop at the breakpoint when the condition is reached. So I start writing this question, and it occurs to me to try:
condition 3 "if i == 495"
and hooray it works. So I guess my questions are: 1. Why the different syntax between the two commands? and 2. Why is the info so confusing? The new info says 'if "if i==495"', but shouldn't that only evaluate to true if 'i==495' evaluates to true?

Your last try is not doing what you think it is doing. When you write:
cond 3 "if i == 495"
the condition is actually the string constant "if i == 495", which is never false. So, the breakpoint stops.
You can see this either by doing print i (for some hits it won't be 495), or by cond 3 "anything goes here!".
The correct syntax was your second attempt:
cond 3 i == 495
I can't say why this isn't triggering for you.

If you are using gdb to debug fortran it might happen that you get a syntax error when trying the reasonable command:
(gdb) b foo.f:10 if i == 0
A syntax error in expression, near `= 0'.
The reason for this is that you must use the old-style fortran syntax (.eq. rather than == and so on) for logical operators:
(gdb) b foo.f:10 if i .eq. 0
Breakpoint 1 at 0x432738: file foo.f, line 10.

Related

How to exit LispWorks REPL debugger, returning to top level typing just a number, like SBCL?

I am currently using LispWorks, and I would like to setup the REPL so that I can exit the debugger simply by typing the number corresponding to (abort) Return to top loop level 0, the same way one can do using SBCL.
Normally, using LispWorks one needs to type :c + [abort option number].
See a trivial example, using LispWorks:
CL-USER 1 > a
Error: The variable A is unbound.
1 (continue) Try evaluating A again.
2 Return the value of :A instead.
3 Specify a value to use this time instead of evaluating A.
4 Specify a value to set A to.
5 (abort) Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
CL-USER 2 : 1 > :c 5
CL-USER 3 >
While using SBCL, just the number will suffice:
* a
debugger invoked on a UNBOUND-VARIABLE in thread
#<THREAD "main thread" RUNNING {10012E0613}>:
The variable A is unbound.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [CONTINUE ] Retry using A.
1: [USE-VALUE ] Use specified value.
2: [STORE-VALUE] Set specified value and use it.
3: [ABORT ] Exit debugger, returning to top level.
(SB-INT:SIMPLE-EVAL-IN-LEXENV A #<NULL-LEXENV>)
0] 3
*
The REPL debugger commands documentation does not seem to list such possibility.
If possible, how can one exit LispWorks REPL debugger, returning to top level typing just a number, like with SBCL?
Basically you can't. It's also more consistent:
* a
debugger invoked on a UNBOUND-VARIABLE in thread
#<THREAD "main thread" RUNNING {10005004F3}>:
The variable A is unbound.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [CONTINUE ] Retry using A.
1: [USE-VALUE ] Use specified value.
2: [STORE-VALUE] Set specified value and use it.
3: [ABORT ] Exit debugger, returning to top level.
(SB-INT:SIMPLE-EVAL-IN-LEXENV A #<NULL-LEXENV>)
0] 4
4
0] 3
*
In the above example with SBCL, the numbers 0...3 choose that debugger option and all other numbers evaluate... that's a bit strange.
LispWorks: simple abort in the debugger
In LispWorks if you would want to use the abort restart, use :a:
CL-USER 1 > a
Error: The variable A is unbound.
1 (continue) Try evaluating A again.
2 Return the value of :A instead.
3 Specify a value to use this time instead of evaluating A.
4 Specify a value to set A to.
5 (abort) Return to level 0.
6 Return to top-level loop.
7 Return from multiprocessing.
Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.
CL-USER 2 : 1 > :a
CL-USER 3 >
There is also the meta-shift-a keyboard command in the LispWorks environment to abort in the debugger. Additionally the restarts are available in the menu and in the right-click context menu. Also one can use the abort icon in the icon bar of the listener/debugger/...
Advantage: you don't have to remember the number of the restart, since that may be different from error to error.
What you see in LispWorks' REPL when an error occur is generated by the error function, as implemented by Lispworks. To change the way options are handled you would have to modify that function, something for which you don't have the documentation since it interacts with LispWorks' REPL in a particular way. So, in short, you can't. (BTW, the 'c' in :c stands for 'continue'.)

Bash operator ++ behavior weired with a constant

By occasionally, I meet a problem when calculating a self-increment operation ++ with a constant, the behavior is weird for me (this is not the original code, I just copied the looks-like lines).
#!/bin/bash
echo "out1="$((++5))
echo "out2="$((5++))
The code snippet looks like about; when I execute it, I got following result:
$ bash test.sh
out1=5
test.sh: line 3: 5++: syntax error: operand expected (error token is "+")
The bash version is:
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
I want to know:
why there is no syntax error for pre-increment operator ?
why the post-increment operate return a value 5, other than 6.
Thanks.
I can't say for sure, I don't feel like browsing the source to learn about the arithmetic expression parser. My guess is:
pre-increment is not actually preincrement, but that you can put any number of + and - symbols before a constant to determine if it's positive or negative. I suspect the parser is seeing $(( +(+5) ))
summary: you're just specifying the number's sign.
as post-incrementing a constant makes no sense (you can't assign the constant 5 with the value 6), it is taken as if you were typing "5 plus ... something" and instead of an arithmetic value you gave another plus sign. So, syntax error, and "operand error" message. Like the parser is seeing $(( (5) + (+) ))
summary: the first plus is OK, the second is an error.

Why AND && logic is used in chained commands in most shells, not OR || logic

I am curious about the logic behind && in continuous commands execution in shell.
Lets see an example: command_a && command_b && command_c
In shell, this means that once a command fails, the consequent commands will not execute and the chain should stop.
If we replace each command by its exit code, the chain becomes, for example this expression 0 && 1 && 0. (command_a succeed, command_b failed, command_c succeed)
If we try evaluating this expression, the evaluation should stop right after the first command, 0 value.
If && logic is replaced by ||, the expression would be more fit to the meaning of original chained command.
0 || 1 || 0.
Expression's evaluation stops after command_b execution
There's a difference between the semantics of a successful command and the representation of success via the numeric value of the exit code. If you consider the abstract "is a command successful", && makes more sense, since the "success" abstract boolean is true. That's why && is used. You need A to run, AND you need B to run.
But, due to the fact that there's usually only one status for success, but many different types of errors, the value 0 has been defined long ago to be used for exit status to indicate success.
So, the exit status of a command can simply not replace the command itself in such an expression. The semantics and the representation are just different.
Check out this post.
"The right side of && will only be evaluated if the exit status of the left side is zero. || is the opposite: it will evaluate the right side only if the left side exit status is nonzero..."
$ false && echo howdy!
$ true && echo howdy!
howdy!
$ true || echo howdy!
$ false || echo howdy!
howdy!
I have seen || used in some shell script too. I think it depends on the occasions. You may use command-a && command-b when you want command-b to be executed only after command-a success.
Likewise, you may use command-a || command-b to deal with the situation when command-a fails.
Update: After reading your question three times I now understand what puzzles you: That 0 represents success, and/or (sic) that logical operators treat it as true. Yes, that can be confusing, coming from C. The other Peter's answer explains that well. I let my original answer stand anyway because it is not "wrong".
It is what logic dictates if commands are impossible to perform or don't make sense unless their predecessors succeeded. That happens quite often: "Retrieve a HTML document from the web, verify the time stamp, parse a value out of it, and write that value as an updated data somewhere." Each step depends on the success of all preceding steps.
If, instead, you have something "retrieve a document from the web, or from the cache, or from disk, or take a default here document, in this order of preference", then the appropriate way to write that is indeed with logical ORs. This happens but is less common.
ORing is a common idiom though for error handling, because subsequent commands are exactly performed if the pervious failed. Consider Perl's idiomatic cmd() || die();. (You have more lives. Phew.)

How to assign a value returned from a function to a variable in GDB script?

For example, consider the following debugging session:
(gdb) break foo
Breakpoint 1 at 0x4004f1: file tst.c, line 5.
(gdb) run
Starting program: /tmp/tst
Breakpoint 1, foo () at tst.c:5
5 return ary[i++];
(gdb) finish
Run till exit from #0 foo () at tst.c:5
Value returned is $1 = 1
(gdb) cont
Continuing.
Breakpoint 1, foo () at tst.c:5
5 return ary[i++];
(gdb) finish
Run till exit from #0 foo () at tst.c:5
Value returned is $2 = 3
After executing a finish command, I get the return value assigned to a
convenience variable (e.g. $1 or $2). Unfortunately, every time the command
is executed, the value is assigned to a different variable. That's the problem,
I cannot write a script which examines the returned value cause I don't know
what variable the value was assigned to.
Why do I need that? I want to set a breakpoint at a certain function but to
stop program execution only if the function has returned a specific value. Something
like this:
break foo
commands
finish
if ($return_value != 42)
continue;
end
end
So the question is: Is there any way to examine in a script the value returned
from a function?
This isn't easy to do from the gdb CLI. Maybe it is impossible purely using the traditional CLI -- because you can have inferior control commands like finish in a breakpoint's commands. This is a longstanding gdb issue.
However, like most automation problems in gdb, it can be solved using the Python API. Now, unfortunately, this approach requires a bit of work on your part.
Essentially what you want to do is subclass the Python FinishBreakpoint class to have it do what you want. In particular you want to write a new command that will set a regular breakpoint in some function; then when this breakpoint is hit, it will instantiate your new FinishBreakpoint class. Your class will have a stop method that will use the return_value of the finish breakpoint as you like.
The first part of your question is straightforward: just use $ to access the most recent value in gdb's value history.
From GDB: Value History
The values printed are given history numbers by which you can refer to them. These are successive integers starting with one. print shows you the history number assigned to a value by printing ‘$num = ’ before the value; here num is the history number.
To refer to any previous value, use ‘$’ followed by the value's history number. The way print labels its output is designed to remind you of this. Just $ refers to the most recent value in the history, and $$ refers to the value before that. $$n refers to the nth value from the end.
But, executing commands following a finish command in a breakpoint command list may not currently be possible; see Tom Tromey's answer for a workaround.

Using logical OR (||) in C-Shell

I have a C-Shell code where I use the following command:
if($#arr == 0 || $arr[1] == "test1") then
It outputs an error message saying "tcsh: arr: Subscript out of range." obviously because the first condition is true. Is it possible to force it to ignore the second condition if the first condition is true?
csh parses the entire line and substitutes variables before evaluating the expression. so in this case, you'd need a nested if because the or condition does not implement short-circuit evaluation with respect to variables.

Resources