Title and Contents |
-g
switch, as follows:
If the problem only occurs in optimized code, use the -g3
switch.
% stty rows 47 ; setenv LINES 47 % stty cols 80 ; setenv COLS 80Following are four basic alternatives for running the debugger on a process:
% ladebug a.out Welcome to the Ladebug Debugger Version n ------------------ object file name: /usr/users/user1/a.out Reading symbolic information ...done (ladebug) stop in main [#1: stop in int main(void) ] (ladebug) run
% ladebug Welcome to the Ladebug Debugger Version n (ladebug) load a.out Reading symbolic information ...done (ladebug) stop in main [#1: stop in int main(void) ] (ladebug) run
% a.out & [2] 27859 % jobs [2] Running ... % ladebug a.out -pid 27859 Attached to process id 27859 ....Press Ctrl/C to interrupt the process.
% a.out & [2] 27859 % jobs [2] Running ... % ladebug (ladebug) attach 27859 a.out Attached to process id 27859 ....Press Ctrl/C to interrupt the process.
NOTE: In the case of Fortran, routine main
at which your
program stops is not your main program unit. Rather, it is a main routine
supplied by the Fortran system that performs some initialization and then
calls your code. Just step forward using the step
command a couple of times (probably twice) and
you will soon step into your code.
(ladebug) you type here
When you enter commands, you use the left and right arrow keys to move within the line and the up and down arrow keys to recall previous commands for editing. When you finish entering a command, press the Enter key to submit the completed line to the debugger for processing.
You can continue a line by ending the line to be continued with a backslash (\) character.
On a blank line, press the Enter key to re-execute the most-recent valid command.
Following are two very useful commands:
(ladebug) help (ladebug) quit
source
command as follows:
(ladebug) source filenameThe
source
command causes the debugger to read and execute
Ladebug commands from
filename
.
Processes contain one or more threads of execution. The threads execute functions. Functions are sequences of instructions that come from source lines within source files.
As you enter debugger commands to manipulate your process, it would be very tedious to have to repeatedly specify which thread, source file, and so on you wish the command to be applied to. To prevent this, each time the debugger stops the process, it re-establishes a static context and a dynamic context for your commands. The components of the static context are independent of this run of your program; the components of the dynamic context are dependent on this run.
You can change most of these individually to point to other instances, as described in the relevant portions of this manual, and the debugger will modify the rest of the static and dynamic context to keep the various components consistent.
After you specify the program (either on the shell command line or
by using the load
command), but before you have requested the debugger to
create the process, you can still do things that seem to require a running
process; for example, you can create breakpoints and examine sources. Any breakpoints
that you create will be inserted into the process as soon as possible after it
executes your program.
To have the debugger create a process (rather than attach to an existing process), you request it to run, specifying, if necessary, any input and output redirection and arguments as follows:
% ladebug a.out Welcome to the Ladebug Debugger Version n (ladebug) run
or
(ladebug) run args
or
(ladebug) run > output-file
or
(ladebug) run args > output-file < input-fileThe result of using any of the preceding command variations is similar to having attached to a running process. The rerun command repeats the previous run command with the same arguments and file redirection.
(ladebug) run ^C Interrupt (for process) Stopping process localhost:27903 (a.out). Thread received signal INT stopped at [int main(int):5 0x120001138] 5 while (argc < 2 && i < 10000000)
(ladebug) run
Thread received signal SEGV
stopped at [void buggy(char*, char*):13 0x120001ba4]
13 output[k] = input[k];
(ladebug) stop in main
[#1: stop in int main(void) ]
(ladebug) run
[1] stopped at [int main(void):182 0x1200023f8]
182 List<Node> nodeList;
(ladebug) watch variable nodeList._firstNode write
[#2: watch variable nodeList._firstNode write ]
(ladebug) cont
[2] Address 0x11fffbf91 was accessed at:
List<Node>::List(void): x_list.cxx
[line 121, 0x120001d94] stq r31, 0(r1)
0x11fffbf90: Old value = 0x000003ffc0002200
0x11fffbf90: New value = 0x0000000000000000
[2] stopped at [List<Node>::List(void):123 0x120001d98]
123 }
/
command to search for a string:
% ladebug a.out
(ladebug) file
x_list.cxx
(ladebug) list 180: 10
180 main()
181 {
182 List<Node> nodeList;
183
184 // add entries to list
185 //
> 186 IntNode* newNode = new IntNode(1);
187 nodeList.append(newNode);
188
189 CompoundNode* cNode = new CompoundNode(12.345, 2);
(ladebug) /CompoundNode
192 CompoundNode* cNode1 = new CompoundNode(3.1415, 7);
Aliases are shorthand forms of longer commands.
This example shows using the W
alias, which lists up to 20 lines
around the current line. A right bracket (>) marks the current line.
(ladebug) alias W
W list $curline - 10:20
(ladebug) W
176
177
178 // The driver for this test
179 //
180 main()
181 {
182 List<Node> nodeList;
183
184 // add entries to list
185 //
> 186 IntNode* newNode = new IntNode(1);
187 nodeList.append(newNode);
188
189 CompoundNode* cNode = new CompoundNode(12.345, 2);
190 nodeList.append(cNode);
191
192 nodeList.append(new IntNode(3));
193
194 IntNode* newNode2 = new IntNode(4);
195 nodeList.append(newNode2);
(ladebug) thread
Thread Name State Substate Policy Pri
------ ------------------------- --------------- ----------- ------------ ---
>* 1 default thread running VP 3 SCHED_OTHER 19
(ladebug) show thread
Thread Name State Substate Policy Pri
------ ------------------------- --------------- ----------- ------------ ---
>* 1 default thread running VP 3 SCHED_OTHER 19
-1 manager thread blk SCS SCHED_RR 19
-2 null thread for slot 0 running VP 1 null thread -1
-3 null thread for slot 1 ready VP 3 null thread -1
-4 null thread for slot 2 new new null thread -1
-5 null thread for slot 3 new new null thread -1
2 threads(0x140000798) blocked cond 3 SCHED_OTHER 19
3 threads+8(0x1400007a0) blocked cond 3 SCHED_OTHER 19
4 threads+16(0x1400007a8) blocked cond 3 SCHED_OTHER 19
5 threads+24(0x1400007b0) blocked cond 3 SCHED_OTHER 19
6 threads+32(0x1400007b8) blocked cond 3 SCHED_OTHER 19
You can select any thread to be the focus of commands that show things. For example:
(ladebug) thread 2
Thread Name State Substate Policy Pri
------ ------------------------- --------------- ----------- ------------ ---
> 2 threads(0x140000798) blocked cond 3 SCHED_OTHER 19
(ladebug) where 4
>0 0x12000226c in ((Node*)0x140004000)->Node::Node() "x_list.cxx":77
#1 0x1200022b8 in ((IntNode*)0x140004000)->IntNode::IntNode(data=2) "x_list.cxx":88
#2 0x120002358 in ((CompoundNode*)0x140004000)->CompoundNode::CompoundNode(fdata=12.345000267028809, idata=2) "x_list.cxx":101
#3 0x12000251c in main() "x_list.cxx":189
(ladebug) up 2
>2 0x120002358 in ((CompoundNode*)0x140004000)->CompoundNode::CompoundNode(fdata=12.345000267028809, idata=2) "x_list.cxx":101
101 CompoundNode::CompoundNode(float fdata, int idata)
(ladebug) list $curline - 10: 20
91 void IntNode::printNodeData() const
92 {
93 cout << " type is integer, value is ";
94 cout << _data << endl;
95 }
96
97
98 //=============================================================================
99 // CompoundNode definition
100 //
> 101 CompoundNode::CompoundNode(float fdata, int idata)
102 :
103 IntNode(idata),
104 _fdata (fdata)
105 {
106 }
107 void CompoundNode::printNodeData() const
108 {
109 cout << " type is compound, value is ";
110 cout << _fdata << endl;
(ladebug) down 1
>1 0x1200022b8 in ((IntNode*)0x140004000)->IntNode::IntNode(data=2) "x_list.cxx":88
88 IntNode::IntNode(int data) : _data(data)
(ladebug) print fdata
12.345000267028809
(ladebug) print idata
2
(ladebug) print idata + 59
61
(ladebug) print this
0x140004000
(ladebug) print *this
class CompoundNode {
_fdata = 0;
_data = 0; // class IntNode
_nextNode = 0x0; // class IntNode::Node
}
(ladebug) run
Thread received signal SEGV
stopped at [void buggy(char*, char*):13 0x120001ba4]
13 output[k] = input[k];
wi
alias lists machine instructions
before and after the current instruction. An asterisk (*)
marks the current instruction.
(ladebug) alias wi
wi ($curpc - 20)/10 i
(ladebug) wi
CompoundNode::CompoundNode(float, int): x_list.cxx
[line 105, 0x120002348] cpys $f17,$f17,$f0
[line 105, 0x12000234c] bis r31, r18, r8
[line 101, 0x120002350] bis r31, r19, r16
[line 101, 0x120002354] bis r31, r8, r17
[line 101, 0x120002358] bsr r26, IntNode::IntNode(int)
*[line 101, 0x12000235c] ldq r18, -32712(gp)
[line 101, 0x120002360] lda r18, 48(r18)
[line 101, 0x120002364] stq r18, 8(r19)
[line 101, 0x120002368] sts $f0, 24(r19)
[line 106, 0x12000236c] bis r31, r19, r0
(ladebug) $pc/10x
0x12000235c: 0x8038 0xa65d 0x0030 0x2252 0x0008 0xb653 0x0018 0x9813
0x12000236c: 0x0400 0x47f3
(ladebug) $pc/6xx
0x12000235c: 0xa65d8038 0x22520030 0xb6530008 0x98130018
0x12000236c: 0x47f30400 0x47f5041a
(ladebug) $pc/2X
0x12000235c: 0x22520030a65d8038 0x98130018b6530008
You can examine individual registers by
using the print
command. To look at all the
registers, use the printregs
command. For example:
(ladebug) print $r16
5368717312
(ladebug) printx $r16
0x140002000
(ladebug) printregs
$r0 [$v0] = 1 $r1 [$t0] = 5
$r2 [$t1] = 4 $r3 [$t2] = 3
$r4 [$t3] = 2 $r5 [$t4] = 5
$r6 [$t5] = 0 $r7 [$t6] = 4
$r8 [$t7] = 2 $r9 [$s0] = 3
$r10 [$s1] = 0 $r11 [$s2] = 4
$r12 [$s3] = 351841472 $r13 [$s4] = 4
$r14 [$s5] = 340620416 $r15 [$s6] = 1
$r16 [$a0] = 5368717312 $r17 [$a1] = 2
$r18 [$a2] = 2 $r19 [$a3] = 5
$r20 [$a4] = 5368717360 $r21 [$a5] = 4
$r22 [$t8] = 1 $r23 [$t9] = 5
$r24 [$t10] = 4396973371008 $r25 [$t11] = 1
$r26 [$ra] = 4831847228 $r27 [$t12] = 0
$r28 [$at] = 4831845184 $r29 [$gp] = 5
$r30 [$sp] = 4831834640 $r31 [$zero]= 0
$f0 = 12.34500026702881 $f1 = 0
$f2 = 0 $f3 = 0
$f4 = 0 $f5 = 0
$f6 = 0.10000000000000001 $f7 = 0.20000000000000001
$f8 = 0.29999999999999999 $f9 = 0.40000000000000002
$f10 = 0.5 $f11 = 0
$f12 = 0 $f13 = 0
$f14 = 0 $f15 = 0
$f16 = 0 $f17 = 0
$f18 = 0 $f19 = 0
$f20 = 0 $f21 = 0
$f22 = 0 $f23 = 0.59999999999999998
$f24 = 12.34500026702881 $f25 = 0
$f26 = 0.69999999999999996 $f27 = 0.80000000000000004
$f28 = 0.90000000000000002 $f29 = 1
$f30 = 1.1000000000000001 $f31 = 0
$pc = 0x12000226c $ps = 0x8
$fpcr = 0x0 $uniq = 0x0
$vfp = 0x11ffff210
Continue until another interesting thing happens |
c
|
cont
|
|
Single step by line, but step over calls |
n
|
next
|
|
Single step to a new line, stepping into calls |
s
|
step
|
|
Continue until control returns to the caller |
return
|
|
|
Single step by instruction, over calls | ni |
nexti
|
|
Single step by instruction, into calls |
si
|
stepi
|
|
The following example demonstrates stepping through lines of source code:
(ladebug) list $curline - 10: 20
172
173 if (i == 1) cout << "The list is empty ";
174 cout << endl << endl;
175 }
176
177
178 // The driver for this test
179 //
180 main()
181 {
> 182 List<Node> nodeList;
183
184 // add entries to list
185 //
186 IntNode* newNode = new IntNode(1);
187 nodeList.append(newNode);
188
189 CompoundNode* cNode = new CompoundNode(12.345, 2);
190 nodeList.append(cNode);
191
(ladebug) next
stopped at [int main(void):186 0x120002440]
186 IntNode* newNode = new IntNode(1);
(ladebug) next 9
stopped at [int main(void):200 0x120002714]
200 CompoundNode* cNode2 = new CompoundNode(10.123, 5);
(ladebug) step
stopped at [CompoundNode::CompoundNode(float, int):101 0x120002350]
101 CompoundNode::CompoundNode(float fdata, int idata)
(ladebug) list $curline - 2: 6
99 // CompoundNode definition
100 //
> 101 CompoundNode::CompoundNode(float fdata, int idata)
102 :
103 IntNode(idata),
104 _fdata (fdata)
(ladebug) step
stopped at [IntNode::IntNode(int):88 0x1200022b4]
88 IntNode::IntNode(int data) : _data(data)
(ladebug) list $curline - 2: 5
86 // IntNode definition
87 //
> 88 IntNode::IntNode(int data) : _data(data)
89 {
90 }
(ladebug) return
stopped at [CompoundNode::CompoundNode(float, int):101 0x12000235c]
101 CompoundNode::CompoundNode(float fdata, int idata)
(ladebug) return
stopped at [int main(void):200 0x120002764]
200 CompoundNode* cNode2 = new CompoundNode(10.123, 5);
(ladebug) step
stopped at [int main(void):201 0x120002794]
201 nodeList.append(cNode2);
(ladebug) step
stopped at [void List<Node>::append(class Node* const):148 0x120001dbc]
148 if (!_firstNode)
(ladebug) list $curline: 8
> 148 if (!_firstNode)
149 _firstNode = node;
150 else {
151 Node* currentNode = _firstNode;
152 while (currentNode->getNextNode())
153 currentNode = currentNode->getNextNode();
154 currentNode->setNextNode(node);
155 }
(ladebug) step 2
stopped at [void List<Node>::append(class Node* const):152 0x120001de0]
152 while (currentNode->getNextNode())
The following example demonstrates stepping at the instruction level:
(ladebug) $curpc - 20/14i
void List<Node>::append(class Node* const): x_list.cxx
[line 149, 0x120001dcc] ldq r3, 24(sp)
[line 149, 0x120001dd0] stq r2, 0(r3)
[line 149, 0x120001dd4] br r31, 0x120001e2c
[line 151, 0x120001dd8] ldq r4, 24(sp)
[line 151, 0x120001ddc] ldq r9, 0(r4)
*[line 152, 0x120001de0] bis r31, r9, r16
[line 152, 0x120001de4] ldq r27, -32584(gp)
[line 152, 0x120001de8] jsr r26, (r27), Node::getNextNode
[line 152, 0x120001dec] ldah gp, 8192(r26)
[line 152, 0x120001df0] lda gp, 25940(gp)
[line 152, 0x120001df4] beq r0, 0x120001e14
[line 153, 0x120001df8] bis r31, r9, r16
[line 153, 0x120001dfc] ldq r27, -32584(gp)
[line 153, 0x120001e00] jsr r26, (r27), Node::getNextNode
(ladebug) stepi
stopped at [void List<Node>::append(class Node* const):152 0x120001de4] ldq r27, -32584(gp)
(ladebug) nexti
stopped at [void List<Node>::append(class Node* const):152 0x120001de8] jsr r26, (r27), Node::getNextNode
(ladebug) stepi
stopped at [class Node* Node::getNextNode(void):81 0x120002284] bis r31, r16, r1
(ladebug) return
stopped at [void List<Node>::append(class Node* const):152 0x120001dec]
152 while (currentNode->getNextNode())
(ladebug) nexti 2
stopped at [void List<Node>::append(class Node* const):152 0x120001df4] beq r0, 0x120001e14
In a program that does not use multiple threads, you can use snapshots to save your state before you step over the call. Then clone that snapshot to position another process just before the call so you can step into it.
The following example shows the stages of a snapshot being used in this way:
(ladebug) next 2
stopped at [int main(void):187 0x1200024b8]
187 nodeList.append(newNode);
(ladebug) list $curline - 10: 20
177
178 // The driver for this test
179 //
180 main()
181 {
182 List<Node> nodeList;
183
184 // add entries to list
185 //
186 IntNode* newNode = new IntNode(1);
> 187 nodeList.append(newNode);
188
189 CompoundNode* cNode = new CompoundNode(12.345, 2);
190 nodeList.append(cNode);
191
192 CompoundNode* cNode1 = new CompoundNode(3.1415, 7);
193 nodeList.append(cNode1);
194
195 nodeList.append(new IntNode(3));
196
(ladebug) save snapshot
# 1 saved at 08:41:46 (PID: 1012).
stopped at [int main(void):187 0x1200024b8]
187 nodeList.append(newNode);
(ladebug) next
stopped at [int main(void):189 0x1200024d0]
189 CompoundNode* cNode = new CompoundNode(12.345, 2);
(ladebug) list $curline - 10: 20
179 //
180 main()
181 {
182 List<Node> nodeList;
183
184 // add entries to list
185 //
186 IntNode* newNode = new IntNode(1);
187 nodeList.append(newNode);
188
> 189 CompoundNode* cNode = new CompoundNode(12.345, 2);
190 nodeList.append(cNode);
191
192 CompoundNode* cNode1 = new CompoundNode(3.1415, 7);
193 nodeList.append(cNode1);
194
195 nodeList.append(new IntNode(3));
196
197 IntNode* newNode2 = new IntNode(4);
198 nodeList.append(newNode2);
(ladebug) clone snapshot
Process has exited
Process 1009 cloned from Snapshot 1.
# 1 saved at 08:41:46 (PID: 1012).
stopped at [int main(void):187 0x1200024b8]
187 nodeList.append(newNode);
(ladebug) list $curline - 10: 20
177
178 // The driver for this test
179 //
180 main()
181 {
182 List<Node> nodeList;
183
184 // add entries to list
185 //
186 IntNode* newNode = new IntNode(1);
> 187 nodeList.append(newNode);
188
189 CompoundNode* cNode = new CompoundNode(12.345, 2);
190 nodeList.append(cNode);
191
192 CompoundNode* cNode1 = new CompoundNode(3.1415, 7);
193 nodeList.append(cNode1);
194
195 nodeList.append(new IntNode(3));
196
fork()
to both
create the snapshot and to clone it.