How to set a breakpoint with ocamldebug

I’m so confused why I can’t seem to set any breakpoints with ocamldebug.

nojaf@nojaf-mbp rescript % ocamldebug /Users/nojaf/Projects/rescript/_build/default/analysis/bin/main.bc 
        OCaml Debugger version 5.3.0

(ocd) help
List of commands: cd complete pwd directory kill pid address help quit shell
environment run reverse step backstep goto finish next start previous print
display source break delete set show info frame backtrace bt up down last
list load_printer install_printer remove_printer

(ocd) step
Loading program... done.
Time: 1 - pc: 3:8488 - module Stdlib
24     (Invalid_argument "index out of bounds")<|a|>
(ocd) list Main
1 open Analysis
2 
3 let help =
4   {|
5 **Private CLI For rescript-vscode usage only**
6 
7 API examples:
8   ./rescript-editor-analysis.exe completion src/MyFile.res 0 4 currentContent.res true
9   ./rescript-editor-analysis.exe definition src/MyFile.res 9 3
10   ./rescript-editor-analysis.exe typeDefinition src/MyFile.res 9 3
11   ./rescript-editor-analysis.exe documentSymbol src/Foo.res
12   ./rescript-editor-analysis.exe hover src/MyFile.res 10 2 true
13   ./rescript-editor-analysis.exe references src/MyFile.res 10 2
14   ./rescript-editor-analysis.exe rename src/MyFile.res 10 2 foo
15   ./rescript-editor-analysis.exe diagnosticSyntax src/MyFile.res
16   ./rescript-editor-analysis.exe inlayHint src/MyFile.res 0 3 25
17   ./rescript-editor-analysis.exe codeLens src/MyFile.res
18 
19 Dev-time examples:
20   ./rescript-editor-analysis.exe dump src/MyFile.res src/MyFile2.res
21   ./rescript-editor-analysis.exe test src/MyFile.res
(ocd) break @Main 92
Can't find any event there.
(ocd) 

I tried various takes on break but nothing seems to do anything.

The most likely explanation is that your Main module was not compiled with -g. Alternatively, if you’re building with dune, it is possible that dune changed the name of your Main module to something else (I’ve seen Dune_exe__Main in some cases, not sure if that will work).

I have it with other modules as well. It is not finding any really.

I’ve added (flags (:standard -g)) but that didn’t help either.

It is a long time since I used ocamldebug, but a note I made for myself at the time as a reminder said this:

Setting a breakpoint can only be done at what is called an “event”, and the program must previously have run to the part of the program where the breakpoint is to be situated so that the relevant code has been previously loaded. Furthermore, setting a breakpoint with dune as the build tool and with internal library files can be challenging. Given an internal library Lib with module Arith and a function sum, you can set a breakpoint at the beginning of the function body with break Lib.Arith.sum. However to set the breakpoint at line 3 of the Lib.Arith module, you have to take account of dune’s name mangling and aliasing, and this becomes break @Lib__Arith 3. (double underscore).

I have no recollection of any of the above. It corresponded to what I found at the time but I do not know if it is still true.

1 Like

From OCaml - The debugger (ocamldebug)

break function
Set a breakpoint at the beginning of function. This works only when the functional value of the identifier function has been computed and assigned to the identifier. Hence this command cannot be used at the very beginning of the program execution, when all identifiers are still undefined; use goto time to advance execution until the functional value is available.

So you first have to proceed past program and Stdlib start-up and initialization, which can be achieved by first running goto 18 (or something like that). Alternatively set a breakpoint in the first line of your “main module”: break @Main 27.

Finally I will iterate @cvine’s dune name mangling warning: An executable module main.ml built with dune will have its module name prefixed into Dune__exe__Main and hence needs to use break @Dune__exe__Main 92 to set a line-numbered breakpoint in it, while one compiled directly with ocamlc uses the less surprising break @Main 92.

There’s more info about this in Byte target can't be debugged with ocamldebug · Issue #4347 · ocaml/dune · GitHub and wrapped_executables - Dune documentation.

Type the command info modules in ocamldebug to list the names of the modules as seen by the debugger.

2 Likes

Once I tried setting break points at various lines in a program, each time getting the no event there error, and I was baffled. I was especially confused because often ocamldebug will adjust the line number to the nearest “event” if it is just a few lines away. Then I finally managed to set a breakpoint, and I ran the program to the breakpoint and listed the code. Then I realized my error. I was looking at the source file on my local machine while debugging the code on a remote machine! The line numbers weren’t the same because the source code wasn’t the same.

I learned that the ocamldebug list command can list specific lines, e.g., list Main 92, even though that isn’t mentioned in the help documentation (i.e., help list). I did not know that I could put the name of a module in the list command until I just read this thread today; so I learned something. (I see now that it is documented in the OCaml 5.3 manual.)

And list Main 92 worked just fine on my program even though the name of the Main module is mangled to “Dune__exe__Main”, and I get:

(ocd) break @Main 92
Can't find any event there.
(ocd) break @Dune__exe__Main 92
Breakpoint 1 at 0:5499172: file src/main.ml, line 92, characters 3-1687

Some of ocamdebug usage difficulties might be eased by improving error messages and documentation a bit.

Thanks all! info modules revealed Dune__exe__Main indeed.

1 Like