This user guide:
http://www.haskell.org/ghc/docs/latest/html/users_guide/ghci-debugger.html
advertises:
Execution can be single-stepped: the evaluator will suspend execution
approximately after every reduction, allowing local variables to be
inspected. This is equivalent to setting a breakpoint at every point
in the program.
Yet, I can find nothing in the document that tells me how to do that. Under the heading:
2.5.2. Single-stepping
It describes how to step from breakpoint to breakpoint. But I don't want to have to set a breakpoint on every line. Was the advertisement false or is there a way to step through a program line by line?
Thanks.
After having set and reached a breakpoint, you can call :step from the debugger.
There are other single-step possibilities. Typing :help once at a breakpoint would tell you more about what you can do.
Okay, I figured it out:
ghci> :step function_name arg1 arg2
...
...
ghci> :step
...
...
ghci> :step
If you forget the function arguments, then you will get the cryptic error message:
<interactive>:138:1:
No instance for (Show (String -> Double))
arising from a use of `print'
Possible fix:
add an instance declaration for (Show (String -> Double))
In a stmt of an interactive GHCi command: print it
...which might lead you to tear your hair out. And if you want to skip to the end:
ghci> :continue
Related
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'.)
I am new to Clojure and want to debug a Clojure file abc.clj that will take user arguments. To run the file, i will do
lein run [arg1 arg2 ..]
I have tried emacs-cider and lighttable, but haven't found a way to input user argument from the beginning.
Maybe you can try the Debux library, and use your REPL to observe results. Seems to me that Clojure is really about the REPL and interactive development.
If I understand what you're trying to do, you should be able to sprinkle debug macros (dbg) throughout your code, then run your code with whatever changes to your args. The various results from the dbg macros will show in your REPL. I'm not sure if you can do this straight from lein, however.
From the README page:
Basic usage
This is a simple example. The macro dbg prints an original form and
pretty-prints the evaluated value on the REPL window. Then it returns
the value without interfering with the code execution.
If you wrap the code with dbg like this,
(* 2 (dbg (+ 10 20))) ; => 60
the following will be printed in the REPL window.
REPL output:
dbg: (+ 10 20) => 30
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.
I often have a need to set a breakpoint on method, print the arguments, and break on a specific argument or continue when not matched. In native code, I would use bp <symbol> "commands". But this is a managed application, so the method is not always JITted. As such, !sos.bpmd is available; however, it does not support a commands arguments. !sosex.mbm is another option and the documentation indicates that it can accept a commands arguments. From !sosex.help mbm:
"command" - Exactly one quoted string parameter may be specified. The contents of this string will be passed on to corresponding native breakpoints as the command parameter.
For further details about these options, see the debugger documentation for the 'bp' command.
The implication is that it this command argument is passed to the native breakpoint commands, such as bp. However, it fails to parse command arguments that the same bp command is able to accept.
Below are my attempts.
0:022> $ Set a breakpoint on Foo.Bar.CBase!Foo.Bar.CBase.set_Item.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item
The breakpoint could not be resolved immediately.
Further attempts will be made as modules are loaded.
Breakpoint set at Foo.Bar.CBase.set_Item(System.String, System.Object) in AppDomain 0000000001f32cc0.
0:022> $ Breakpoint set. Check the native address.
0:022> !sosex.mbl
AppDomain 0000000001eceee0
--------------------------
0 eu: disable Foo.Bar.CBase!Foo.Bar.CBase.SET_ITEM ILOffset=0: pass=1 oneshot=false thread=ANY
AppDomain 0000000001f32cc0
--------------------------
0 e : disable Foo.Bar.CBase!Foo.Bar.CBase.SET_ITEM ILOffset=0: pass=1 oneshot=false thread=ANY
Foo.Bar.CBase!Foo.Bar.CBase.set_Item(string, object)
0 e 000007ff005cc799
0:022> $ Clear the breakpoint.
0:022> $ !sosex.mbc 0
0:022> $ Set breakpoint on same address with command argument.
0:022> bp 000007ff005cc799 "as /mu ${/v:col} (#rdx+0x10); .block { .printf \"Column: %mu, Value: %mu\\n\", #rdx+10, #r8+10; .if (0 != $scmp( \"${col}\", \"opt_id\")) { gc } }"
0:022> $ Check the set breakpoint.
0:022> bl
0 e 000007ff`005cc799 0001 (0001) 0:**** "as /mu ${/v:col} (#rdx+0x10); .block { .printf \"Column: %mu, Value: %mu\\n\", #rdx+10, #r8+10; .if (0 != $scmp( \"${col}\", \"opt_id\")) { gc } }"
0:022> $ Continue execution.
0:022> g
Column: abc_id, Value: 80
Column: hoge_id, Value: N
Column: priority, Value:
Column: opt_id, Value: ZEI
000007ff`005cc799 488b542430 mov rdx,qword ptr [rsp+30h] ss:00000000`056cae00=000000013f7ed498
0:022> $ Outputs arguments and continues on non-match. Breaks on match. Expected results.
The commands argument seems to be valid and does as I desire. Such breakpoints are a frequent task, so I would much prefer to set the whole thing with a single command rather than go through the above multiple steps. As far as I can determine from the sosex.mbm documentation, I should be able to do the following:
0:022> $ Cleanup. Clear the breakpoint.
0:022> bc 0
0:022> $ Ensure that the alias is not defined.
0:022> ad /q ${/v:col}
0:022> $ Try to set the same breakpoint with sosex.mbm.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "as /mu ${/v:col} (#rdx+0x10); .block { .printf \"Column: %mu, Value: %mu\\n\", #rdx+10, #r8+10; .if (0 != $scmp( \"${col}\", \"opt_id\")) { gc } }"
syntax error
^ Quotes required in ' .printf \"Column: %mu, Value: %mu\\n\", #rdx+10, #r8+10; .if (0 != $scmp( \"${col}\", \"opt_id\")) { gc } '
It fails, indicating that quotes are required, but I cannot determine where. The syntax is a bit complicated, so lets try something a little simpler:
0:022> $ Output RDX and R8 when the breakpoint is hit.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r #rdx; r #r8"
syntax error
^ Syntax error in '!sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r #rdx; r #r8"'
This time it is a syntax error, but again I cannot determine where. Lets try another one.
0:022> $ Output RDX when the breakpoint is hit, and then continue.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r #rdx; gc"
syntax error
^ Extra character error in '!sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r #rdx; gc"'
Another error, but this time about an extra character, but it looks OK to me. Lets try something even easier.
0:022> $ Output RDX when the breakpoint is hit.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r #rdx"
The breakpoint could not be resolved immediately.
Further attempts will be made as modules are loaded.
Breakpoint set at Foo.Bar.CBase.set_Item(System.String, System.Object) in AppDomain 0000000001f32cc0.
Success at last. The conclusion that I draw from this is that sosex.mbm can only accept a single command argument as long as it does not contain multiple statements. As the documentation indicates, if the single command argument is merely being passed to the native breakpoint (such as bp), then there should be no such restriction.
Is this behavior expected or am I doing something wrong? Is there another way to accomplish this? I can use the above workaround, but I often need to set such breakpoints are so would much rather find a more direct way to do this.
Please note that I am using version 4.5.0.783 of sosex. This is the latest version available for download.
You're not doing anything wrong. I can see why your command with embedded quotes would fail. SOSEX isn't terribly sophisticated about parsing the quoted string. However, your simple commands should succeed. I'll work on this and get back to you.
I have problem with n+k pattern.
I want to enable it, but i don't know how.
I have added {-# LANGUAGE NPlusKPatterns #-} at the beggining of my .hs file, but it didn't work.
Also I try typping in my ghci console -NPlusKPatterns but is just gives me errors.
You need to type
:set -XNPlusKPatterns
in ghci to enable them.
For completeness I'll point out that if you load ghci from the command prompt instead of running winghci, you can load it with ghci -XNPlusKPatterns instead of interactively doing :set -XNPlusKPatterns.
You can check whether it's working by defining an n+k pattern interactively. Here's an example session:
Prelude> let fact 0 = 1; fact (n+1) = (n+1)*fact n in fact 5
<interactive>:8:23: Parse error in pattern: n + 1
Prelude> :set -XNPlusKPatterns
Prelude> let fact 0 = 1; fact (n+1) = (n+1)*fact n in fact 5
120