1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
|
\newpage
\section{Debugging}
\label{Debugging}
%HEVEA\cutdef[1]{subsection}
\subsection{Introduction}
The GNU Prolog debugger provides information concerning the control flow of
the program. The debugger can be fully used on consulted predicates (i.e.
byte-code). For native compiled code only the calls/exits are traced, no
internal behavior is shown. Under the debugger it is possible to exhaustively
trace the execution or to set spy-points to only debug a specific part of the
program. Spy-points allow the user to indicate on which predicates the
debugger has to stop to allow the user to interact with it. The debugger uses
the ``procedure box control flow model'', also called the Byrd Box model
since it is due to Lawrence Byrd.
\subsection{The procedure box model}
The procedure box model of Prolog execution provides a simple way to show
the control flow. This model is very popular and has been adopted in many
Prolog systems (e.g. SICStus Prolog, Quintus Prolog,\ldots). A good
introduction is the chapter 8 of ``Programming in Prolog'' of Clocksin \&
Mellish~\cite{Clock}. The debugger executes a program step by step tracing an
invocation to a predicate (\texttt{call}) and the return from this predicate
due to either a success (\texttt{exit}) or a failure (\texttt{fail}). When a
failure occurs the execution backtracks to the last predicate with an
alternative clause. The predicate is then re-invoked (\texttt{redo}).
Another source of change of the control flow is due to exceptions. When an
exception is raised from a predicate (\texttt{exception}) by
\IdxPB{throw/1} \RefSP{catch/3} the control is given back to the most
recent predicate that has defined a handler to recover this exception using
\IdxPB{catch/3} \RefSP{catch/3}. The procedure box model shows these
different changes in the control flow, as illustrated here:
\InsertImage{debug-box}
Each arrow corresponds to a \emph{port}. An arrow to the box indicates
that the control is given to this predicate while an arrow from the box
indicates that the control is given back from the procedure. This model
visualizes the control flow through these five ports and the connections
between the boxes associated with subgoals. Finally, it should be clear that a
box is associated with one invocation of a given predicate. In particular, a
recursive predicate will give raise to a box for each invocation of the
predicate with different entries/exits in the control flow. Since this might
get confusing for the user, the debugger associates with each box a unique
identifier (i.e. the invocation number).
\subsection{Debugging predicates}
\subsubsection{\AddDBD{trace/0}%
\AddDBD{debug/0}%
\AddDBD{debugging/0}%
\AddDBD{notrace/0}%
\AddDBD{nodebug/0}%
\AddDBD{wam\_debug/0}%
Running and stopping the debugger \label{Running-and-stopping-the-debugger}}
\texttt{trace/0} activates the debugger. The next invocation of a predicate
will be traced.
\texttt{debug/0} activates the debugger. The next invocation of a predicate
on which a spy-point has been set will be traced.
It is important to understand that the information associated with the control
flow is only available when the debugger is on. For efficiency reasons, when
the debugger is off the information concerning the control flow (i.e. the
boxes) is not retained. So, if the debugger is activated in the middle of a
computation (by a call to \texttt{debug/0} or \texttt{trace/0} in the
program or after the interrupt key sequence (\texttt{Ctl-C}) by choosing
\texttt{trace} or \texttt{debug}), information prior to this point is not
available.
\texttt{debugging/0}: prints onto the terminal information about the current
debugging state (whether the debugger is switched on, what are the leashed
ports, spy-points defined,\ldots).
\texttt{notrace/0} or \texttt{nodebug/0} switches the debugger off.
\texttt{wam\_debug/0} invokes the sub-debugger devoted to the WAM data
structures \RefSP{The-WAM-debugger}. It can be also invoked using the
\texttt{W} debugger command \RefSP{Debugger-commands}.
\subsubsection{\AddDBD{leash/1}%
Leashing ports \label{Leashing-ports}}
\texttt{leash(Ports)} requests the debugger to prompt the user, as
he creeps through the program, for every port defined in the \texttt{Ports}
list. Each element of \texttt{Ports} is an atom in \texttt{call},
\texttt{exit}, \texttt{redo}, \texttt{fail}, \texttt{exception}.
\texttt{Ports} can also be an atom defining a shorthand:
\begin{itemize}
\item \IdxDKD{full}: equivalent to \texttt{[call, exit, redo, fail,
exception]}
\item \IdxDKD{half}: equivalent to \texttt{[call, redo]}
\item \IdxDKD{loose}: equivalent to \texttt{[call]}
\item \IdxDKD{none}: equivalent to \texttt{[]}
\item \IdxDKD{tight}: equivalent to \texttt{[call, redo, fail,
exception]}
\end{itemize}
When an unleashed port is encountered the debugger continues to show the
associated goal but does not stop the execution to prompt the user.
\subsubsection{%
\AddDBD{spy/1}%
\AddDBD{nospy/1}%
\AddDBD{nospyall/0}%
\AddDBD{spypoint\_condition/3}%
Spy-points \label{Spy-points}}
When dealing with big sources it is not very practical to creep through the
entire program. It is preferable to define a set of spy-points on
interesting predicates to be prompted when the debugger reaches one of these
predicates. Spy-points can be added either using \texttt{spy/1} (or
\texttt{spypoint\_condition/3}) or dynamically when prompted by the debugger
using the \texttt{+} (or \texttt{*}) debugger command
\RefSP{Debugger-commands}. The current mode of leashing does not
affect spy-points in the sense that user interaction is requested on
every port.
\texttt{spy(PredSpec)} sets a spy-point on all the predicates given by
\texttt{PredSpec}. \texttt{PredSpec} defines one or several predicates and
has one of the following forms:
\begin{itemize}
\item \texttt{[PredSpec1, PredSpec2,\ldots]}: set a spy-point for each
element of the list.
\item \texttt{Name}: set a spy-point for any predicate whose name is
\texttt{Name} (whatever the arity).
\item \texttt{Name/Arity}: set a spy-point for the predicate whose name is
\texttt{Name} and arity is \texttt{Arity}.
\item \texttt{Name/A1-A2}: set a spy-point for the each predicate whose name
is \texttt{Name} and arity is between \texttt{A1} and \texttt{A2}.
\end{itemize}
It is not possible to set a spy-point on an undefined predicate.
The following predicate is used to remove one or several spy-points:
\texttt{nospy(PredSpec)} removes the spy-points from the specified
predicates.
\texttt{nospyall/0} removes all spy-points:
It is also possible to define conditional spy-points.
\texttt{spypoint\_condition(Goal, Port, Test)} sets a
conditional spy-point on the predicate for \texttt{Goal}. When the debugger
reaches a conditional spy-point it only shows the associated goal if the
following conditions are verified:
\begin{itemize}
\item the actual goal unifies with \texttt{Goal}.
\item the actual port unifies with \texttt{Port}.
\item the Prolog goal \texttt{Test} succeeds.
\end{itemize}
\subsection{Debugging messages}
We here described which information is displayed by the debugger when it
shows a goal. The basic format is as follows:
\OneLine{\Param{S N M Port}:~\Param{Goal} ?}
\Param{S} is a spy-point indicator: if there is a spy-point on the
current goal the \texttt{+} symbol is displayed else a space is displayed.
\Param{N} is the invocation number. This unique number can be used
to correlate the trace messages for the various ports, since it is unique
for every invocation. \Param{M} is an index number which
represents the number of direct ancestors of the goal (i.e. the current
depth of the goal). \Param{Port} specifies the particular port
(\texttt{call}, \texttt{exit}, \texttt{fail}, \texttt{redo},
\texttt{exception}). \Param{Goal} is the current goal (it is then
possible to inspect its current instantiation) which is displayed using
\IdxPB{write\_term/3} with \texttt{quoted(true)} and
\texttt{max\_depth(\Param{D})} options \RefSP{write-term/3}. Initially
\Param{D} (the print depth) is set to 10 but can be redefined
using the \texttt{{\lt}} debugger command \RefSP{Debugger-commands}. The
\texttt{?} symbol is displayed when the debugger is waiting a command from
the user. (i.e. \texttt{Port} is a leashed port). If the port is unleashed,
this symbol is not displayed and the debugger continues the execution
displaying the next goal.
\subsection{Debugger commands}
\label{Debugger-commands}
When the debugger reaches a leashed port it shows the current goal followed
by the \texttt{?} symbol. At this point there are many commands available.
Typing \texttt{RETURN} will creep into the program. Continuing to creep will
show all the control flow. The debugger shows every port for every predicate
encountered during the execution. It is possible to select the ports at
which the debugger will prompt the user using the built-in predicate
\IdxDB{leash/1} \RefSP{Leashing-ports}. Each command is only one
character long:
\begin{tabular}{|c|c|p{10.4cm}|}
\hline
Command & Name & Description \\
\hline\hline
\texttt{RET} or \texttt{c} & creep & single-step to the next port \\
\hline
\texttt{l} & leap & continue the execution only stopping when a goal with a
spy-point is reached \\
\hline
\texttt{s} & skip & skip over the entire execution of the current goal. No
message will be shown until control returns \\
\hline
\texttt{G} & go to & ask for an invocation number and continue the execution
until a port is reached for that invocation number \\
\hline
\texttt{r} & retry & try to restart the invocation of the current goal by
failing until reaching the invocation of the goal. The state of
execution is the same as when the goal was initially invoked (except when
using side-effect predicates) \\
\hline
\texttt{f} & fail & force the current goal to fail immediately \\
\hline
\texttt{w} & write & show the current goal using \texttt{write/2}
\RefSP{write-term/3}
\\
\hline
\texttt{d} & display & show the current goal using \texttt{display/2}
\RefSP{write-term/3} \\
\hline
\texttt{p} & print & show the current goal using \texttt{print/2}
\RefSP{write-term/3}
\\
\hline
\texttt{e} & exception & show the pending exception. Only applicable to an
\texttt{exception} port \\
\hline
\texttt{g} & ancestors & show the list of ancestors of the current goal \\
\hline
\texttt{A} & alternatives & show the list of ancestors of the current goal
combined with choice-points \\
\hline
\texttt{u} & unify & ask for a term and unify the current goal with this
term. This is convenient for getting a specific solution. Only available at
a \texttt{call} port \\
\hline
\texttt{.} & father file & show the Prolog file name and the line number
where the current predicate is defined \\
\hline
\texttt{n} & no debug & switch the debugger off. Same as \IdxDB{nodebug/0}
\RefSP{Running-and-stopping-the-debugger} \\
\hline
\texttt{=} & debugging & show debugger information. Same as
\IdxDB{debugging/0} \RefSP{Running-and-stopping-the-debugger} \\
\hline
\texttt{+} & spy this & set a spy-point on the current goal. Uses
\IdxDB{spy/1} \RefSP{Spy-points} \\
\hline
\texttt{-} & nospy this & remove a spy-point on the current goal. Uses
\IdxDB{nospy/1} \RefSP{Spy-points} \\
\hline
\texttt{*} & spy conditionally & ask for a term \texttt{Goal, Port, Test}
(terminated by a dot) and set a conditional spy-point on the current
predicate. \texttt{Goal} and the current goal must have the same predicate
indicator. Uses \IdxDB{spypoint\_condition/3} \RefSP{Spy-points} \\
\hline
\texttt{L} & listing & list all the clauses associated with the current
predicate. Uses \IdxPB{listing/1} \RefSP{listing/1} \\
\hline
\texttt{a} & abort & abort the current execution. Same as \IdxPB{abort/0}
\RefSP{abort/0} \\
\hline
\texttt{b} & break & invoke a recursive top-level. Same as \IdxPB{break/0}
\RefSP{abort/0} \\
\hline
\texttt{@} & execute goal & ask for a goal and execute it \\
\hline
\texttt{{\lt}} & set print depth & ask for an integer and set the print
depth to this value (\texttt{-1} for no depth limit) \\
\hline
\texttt{h} or \texttt{?} & help & display a summary of available commands \\
\hline
\texttt{W} & WAM debugger & invoke the low-level WAM debugger
\RefSP{The-WAM-debugger} \\
\hline
\end{tabular}
\subsection{The WAM debugger}
\label{The-WAM-debugger}
In some cases it is interesting to have access to the \Idx{WAM} data
structures. This sub-debugger allows the user to inspect/modify the contents
of any stack or register of the WAM. The WAM debugger is invoked
using the built-in predicate \IdxDB{wam\_debug/0} \RefSP{Running-and-stopping-the-debugger} or the \texttt{W} debugger command \RefSP{Debugger-commands}. The following table presents the specific commands of the WAM
debugger:
\begin{tabular}{|l|l|}
\hline
Command & Description \\
\hline\hline
\texttt{write} \Param{A} [\Param{N}] & write
\Param{N} terms starting at the address \Param{A} using \texttt{write/1}
\RefSP{write-term/3} \\
\hline
\texttt{data} \Param{A} [\Param{N}] & display \Param{N} words starting at
the address \Param{A} \\
\hline
\texttt{modify} \Param{A} [\Param{N}] & display and modify \Param{N} words
starting at the address \Param{A} \\
\hline
\texttt{where} \Param{A} & display the real address corresponding to
\Param{A} \\
\hline
\texttt{what} \Param{RA} & display what corresponds to the real address
\Param{RA} \\
\hline
\texttt{deref} \Param{A} & display the dereferenced word starting at the
address \Param{A} \\
\hline
\texttt{envir} [\Param{SA}] & display the contents of the environment
located at \Param{SA} (or the current one) \\
\hline
\texttt{backtrack} [\Param{SA}] & display the contents of the choice-point
located at \Param{SA} (or the current one) \\
\hline
\texttt{backtrack all} & display all choice-points \\
\hline
\texttt{quit} & quit the WAM debugger \\
\hline
\texttt{help} & display a summary of available commands \\
\hline
\end{tabular}
In the above table the following conventions apply:
\begin{itemize}
\item elements between [ and ] are optional.
\item \Param{N} is an optional integer (defaults to 1).
\item \Param{A} is a WAM address, its syntax is:
\Param{BANK\_NAME} [ \texttt{[ \Param{N} ]} ], i.e. a bank name
possibly followed by an index (defaults to 0). \Param{BANK\_NAME}
is either:
\begin{itemize}
\item \texttt{reg}: WAM general register (stack pointers, continuation,
...).
\item \texttt{x}: WAM X register (temporary variables, i.e. arguments).
\item \texttt{y}: WAM Y register (permanent variables).
\item \texttt{ab}: WAM X register saved in the current choice-point.
\item \Param{STACK\_NAME}: WAM stack
(\Param{STACK\_NAME} in \texttt{local}, \texttt{global}, \texttt{trail},
\texttt{cstr}).
\end{itemize}
\item \Param{SA} is a WAM stack address, i.e.
\texttt{\Param{STACK\_NAME}} [ \texttt{[ \Param{N} ]} ] (special case of
WAM addresses).
\item \Param{RA} is a real address, its syntax is the syntax of C
integers (in particular the notation \texttt{0x\ldots} is recognized).
\end{itemize}
It is possible to only use the first letters of a commands and bank names
when there is no ambiguity. Also the square brackets \texttt{[} \texttt{]}
enclosing the index of a bank name can be omitted. For instance the
following command (showing the contents of 25 consecutive words of the
global stack from the index 3): \texttt{data global[3] 25} can be
abbreviated as: \texttt{d g 3 25}.
%HEVEA\cutend
|