With Ladebug, you can debug more than one program or process. This chapter explains how to:
In addition, it presents a sample multiprocess debugging session.
For information about multiprocess debugging from the window interface, see Chapter 5.
You can bring a process into debugger control in the following ways:
-k flag for local kernel
debugging).
load command or attach to a running process using
the attach command.
$catchforks is set
to 1, Ladebug keeps track of newly forked processes.
For more information on the various ways to invoke Ladebug, see Section 1.4.
Use the show process command to display the currently
executing process or all processes in your application. The syntax
is as follows:
show process show process * show process all
If you specify the show process command without a
qualifier, Ladebug displays information for the current process
only. Using the asterisk (*) or the all option
displays information for all processes. For each process listed,
Ladebug shows the process ID, image file, the number of threads, and
state.
After bringing a process under debugger control, you can switch
between processes using the process command. This sets
the current process. The syntax is as follows:
process process [process_id | image_file | debugger_variable]
Specify a specific process using the process ID number or the name of the image. Ladebug sets the current process context to the process ID or the process that runs the binary image. If there are more than one processes running the same binary image, Ladebug warns you and leaves the process context unchanged.
The debugger variables $childprocess and
$parentprocess can also be specified in place of the
process ID. (Ladebug automatically sets these variables when an
application forks a child process.)
The process command without any argument displays
information for the current process only.
The load command reads the symbol table information of
an image file and a core file.
To debug a core file, specify the name of the core file with the
image file. After loading a program, specify the run
command to start execution. The syntax is as follows:
load [image_file [core_file]]
Use the unload command to remove the process-related
information. The syntax of the unload command is as
follows:
unload [process_id | image_file]
The unload command removes the symbol table
information if the debuggee process isn't running or stopped. You
can specify the detach to release control of the
running process or the kill command to terminate the
debugger process if the process is created by Ladebug.
If you do not specify a process ID or image file, Ladebug unloads the current process.
Example 20-1 demonstrates the use of Ladebug commands to debug a multiprocess application.
In the first part of the program, the process command
shows the current process. The load lets you load
an image or core file. Specifying show process all
displays a list of processes, running or stopped.
$ ladebug
Welcome to the Ladebug Debugger Version 4.0-9
(ladebug) process
There is no current process.
You may start one by using the `load' or `attach' commands.
(ladebug) load a.out
Reading symbolic information ...done
(ladebug) process1
Current Process: localhost:18340 (a.out).
(ladebug) show process all2
>localhost:18340 (a.out) Unstarted.
(ladebug) load file-func
Reading symbolic information ...done
(ladebug) process
Current Process: localhost:18551 (file-func).3
(ladebug) show process all4
localhost:18340 (a.out) Unstarted.
>localhost:18551 (file-func) Unstarted.
(ladebug) process 183405
(ladebug) process
Current Process: localhost:18340 (a.out).
(ladebug) list 16
1
2 int main(int argc, char* argv[])
3 {
4 int a = sizeof(**argv);
5 int b = sizeof(+(**argv));
6 int c = sizeof(-(**argv));
7 return a+b+c;
8 }
file-func , Ladebug displays a
new current process (process 18551).
Switching between processes sets the current process context, as shown in Example 20-2.
(ladebug) process 185511
(ladebug) process
Current Process: localhost:18551 (file-func).
(ladebug) list 12
1
2
3 #include <stdio.h>
4
5 int gfi = 100;
6
7 int g1 = 10;
8
9 int funcA(i) {
10
11 int a, x;
12 x = 1;
13 a = i + g1 + x;
14 return a;
15 }
16
17 int funcB(i) {
18
19 int a;
20 a = i;
21 return a;
This section describes Ladebug's support for debugging programs that fork a child process and/or execs a program.
Ladebug contains the following predefined variables that you set for debugging a program that fork and/or execs. By default, the settings are turned off. When activated, the settings apply to all processes you debug.
$catchexecs - When set to 1, this variable
instructs the debugger to notify the user and stop the program
when a program execs. The default is 0.
$catchforks - When set to 1, this variable
instructs the debugger to notify the user when a program forks
a child process. The child process stops and is brought under
debugger control. By default, the parent process is not stopped.
The default is 0.
$stopparentonfork -When set to 1, this
variable instructs the debugger to stop the parent process when a
program forks a child process. The default is 0.
When a fork occurs, Ladebug automatically sets the
debugger variables $childprocess and
$parentprocess to the new child or parent process ID.
All examples in this section assume these variables are set.
Set $catchforks to 1 to instruct Ladebug to to keep
track of newly forked processes when a child process is forked.
Ladebug stops the child process immediately after the fork occurs.
The child process inherits all breakpoints from the parent process.
It also inherits the signals list for the catch/ignore
commands from the parent process.
The child process runs the same image file as the parent process
and the process context is unchanged. You can switch to the child
process using the process command.
When the child process finishes, you cannot rerun the child process. By setting the process context to the parent process, you can rerun the program .
Before you debug you application, you can check the setting of
the predefined variables using the set command, as
shown in Example 20-3. The default
settings for $catchforks, $catchexecs,
and $stoponparentfork are all 0. In Example 20-3, these variables appear
highlighted for illustration.
$ ladebug mp-fork Welcome to the Ladebug Debugger Version 4.0-10 ------------------ object file name: mp-fork Reading symbolic information ...done (ladebug) set $ascii = 1 $beep = 1 $catchexecs = 0 $catchforks = 0 $curevent = 0 $curfile = "mp-fork.c" . . . $stopparentonfork = 0 $threadlevel = "decthreads" $verbose = 0
If your programs frequently fork or exec, you may want to set these
variables in your .dbxinit initialization file.
To instruct Ladebug to report when the program forks a child
process, set the $catchforks predefined variable to
1, as follows:
(ladebug) set $catchforks=1
In Example 20-4, when you run the program, Ladebug notifies you that the child process has stopped. The parent process continues to run.
(ladebug) run
Process 200 forked. The child process is 201.
Process 201 stopped on fork. 1
stopped at [void main(void):14 0x120001248] 2
14 if ((pid=fork()) == 0)
Process has exited with status 18 3
(ladebug) show process all 4
>localhost:200 (mp-fork) dead.
\_localhost:201 (mp-fork) stopped.
(ladebug)
In Example 20-5, the process context is changed. Listing the source code shows the source for the child process.
(ladebug) process 201 1
(ladebug) show process all
localhost:200 (mp-fork) dead.
> \_localhost:201 (mp-fork) stopped. 2
(ladebug) process
Current Process: localhost:201 (mp-fork).
(ladebug) list 3
15 {
16 printf("about to exec\n");
17 execlp("./c_whatis", "./c_whatis", NULL);
18 perror(" execve failed.");
19 }
20
21 else if (pid != -1)
22 {
23 printf("in parent process\n");
24 }
25
26 else
27 {
28 printf("Error in fork!");
29 exit(0);
30 }
31 }
You can continue to debug the current process (the child process). When the child process finishes, you cannot rerun the child process. By setting the process context to the parent process, you can rerun the program, as shown in Example 20-6.
(ladebug) next
stopped at [void main(void):16 0x12000125c]
16 printf("about to exec\n");
(ladebug) next
about to exec
stopped at [void main(void):17 0x120001274]
17 execlp("./c_whatis", "./c_whatis", NULL);
(ladebug) next
result of foo = 5040
result of foo = 5040
result of baz = 720
factorial(1) = 1
factorial(2) = 2
factorial(3) = 6
factorial(4) = 24
factorial(5) = 120
factorial(6) = 720
factorial(7) = 5040
factorial(8) = 40320
abcdefghij
abcdefghij
Process has exited with status 0 1
(ladebug) show process all
localhost:200 (mp-fork) dead.
> \_localhost:201 (mp-fork) dead.
(ladebug) rerun 2
Error: cannot restart existing process.
(ladebug) process 200 3
(ladebug) rerun 4
Process 200 forked. The child process is 201.
Process 201 stopped on fork.
stopped at [void main(void):14 0x120001248]
14 if ((pid=fork()) == 0)
in parent process
Process has exited with status 18
(ladebug)
rerun .
In this scenario, you set the predefined variable $catchforks
and $stopparentonfork to 1. Setting
$catchforks to 1 tells Ladebug to notify the user
when the program forks and stop the child process. By setting
$stopparentonfork to 1, the parent process also
stops when the program forks a child process. The variable
$stopparentonfork has no effect when $catchforks
is set to 0.
To instruct Ladebug to report when the program forks a child
process and stop the parent and child processes, set the variables
$catchforks and $stopparentonfork to 1,
as follows:
(ladebug) set $catchforks=1 (ladebug) set $stopparentonfork=1
In Example 20-7, Ladebug stops
the parent process when it forks the child process. The current
context is the parent process. You can change the process context to
the child process using the process command.
(ladebug) run
Process 200 forked. The child process is 201.
Process 201 stopped on fork.
stopped at [void main(void):14 0x120001248]
14 if ((pid=fork()) == 0)
Process 200 stopped on fork.
stopped at [void main(void):14 0x120001248] 1
14 if ((pid=fork()) == 0)
(ladebug) show process all
>localhost:200 (mp-fork) stopped.
\_localhost:201 (mp-fork) stopped.
(ladebug) process 201 2
(ladebug) show process all
localhost:200 (mp-fork) stopped.
> \_localhost:201 (mp-fork) stopped.
(ladebug) list 3
15 {
16 printf("about to exec\n");
17 execlp("./c_whatis", "./c_whatis", NULL);
18 perror(" execve failed.");
19 }
20
21 else if (pid != -1)
22 {
23 printf("in parent process\n");
24 }
25
26 else
27 {
28 printf("Error in fork!");
29 exit(0);
30 }
31 }
In Example 20-8, you continue to debug the current process (the child process). When the child process finishes, you can switch to the parent process and continue debugging.
(ladebug) next 1
stopped at [void main(void):16 0x12000125c]
LDBGD$:[SLOVENKAI.LADEBUG.MANUAL]LADEBUG_CH_MULTIPROC.SDML;19
(ladebug) next
about to exec
sstopped at [void main(void):17 0x120001274]
17 execlp("./c_whatis", "./c_whatis", NULL);
(ladebug) next
result of foo = 5040
result of foo = 5040
result of baz = 720
factorial(1) = 1
factorial(2) = 2
factorial(3) = 6
factorial(4) = 24
factorial(5) = 120
factorial(6) = 720
factorial(7) = 5040
factorial(8) = 40320
abcdefghij
abcdefghij
Process has exited with status 0 2
(ladebug) show process all
localhost:200 (mp-fork) stopped.
> \_localhost:201 (mp-fork) dead.
(ladebug) process 200
(ladebug) list 3
15 {
16 printf("about to exec\n");
17 execlp("./c_whatis", "./c_whatis", NULL);
18 perror(" execve failed.");
19 }
20
21 else if (pid != -1)
22 {
23 printf("in parent process\n");
24 }
25
26 else
27 {
28 printf("Error in fork!");
29 exit(0);
30 }
31 }
(ladebug) next
stopped at [void main(void):21 0x1200012b4]
21 else if (pid != -1)
(ladebug) next
stopped at [void main(void):23 0x1200012c0]
23 printf("in parent process\n");
(ladebug) cont
in parent process
Process has exited with status 18 4
Set $catchexecs to 1 to instruct Ladebug to notify the
user when the program execs. The program stops before executing any
user program code or static initializations that are passed to the
exec system call. You can debug the newly exec'd program using basic
debugging techniques. Ladebug keeps a history of the progression of
the exec'd binary files.
In the following scenario, you set the predefined variable
$catchforks and $catchexecs to 1. Ladebug
will notify you when an exec occurs. Because $catchforks
was set, you will be notified of any execs in the child
process.
To instruct Ladebug to report when a program execs on the current
process context, set the variables $catchexecs and
$catchforks to 1, as follows:
(ladebug) set $catchexecs=1 (ladebug) set $catchforks=1
When you run the program in Example 20-9, Ladebug notifies you that an exec occurred on the current context and that the child process has stopped on the runtime-loader entry point.
(ladebug) run
Process 200 forked. The child process is 201.
Process 201 stopped on fork.
stopped at [void main(void):14 0x120001248]
14 if ((pid=fork()) == 0)
in parent process
Process has exited with status 18
(ladebug) show process all
>localhost:200 (mp-fork) dead.
\_localhost:201 (mp-fork) stopped.
(ladebug) process 201 1
(ladebug) list
15 {
16 printf("about to exec\n");
17 execlp("./c_whatis", "./c_whatis", NULL); 2
18 perror(" execve failed.");
19 }
20
21 else if (pid != -1)
22 {
23 printf("in parent process\n");
24 }
25
26 else
27 {
28 printf("Error in fork!");
29 exit(0);
30 }
31 }
(ladebug) next
stopped at [void main(void):16 0x12000125c]
16 printf("about to exec\n");
(ladebug) next
about to exec
stopped at [void main(void):17 0x120001274]
17 execlp("./c_whatis", "./c_whatis", NULL);
(ladebug) next
The process 201 has execed the image `./c_whatis'. 3
stopped at [???:62 0x3ff8001c3b8] 4
62 i = 1;
main
routine.
In Example 20-10, you can set breakpoints in the current process (child process). Ladebug shows the current process and the current executing program.
(ladebug) stop in main 1
[#1: stop in int main(void) ]
(ladebug) c
[1] stopped at [int main(void):62 0x1200013a4]
62 i = 1;
(ladebug) list
63 foo();
64 baz(x,3,x+1);
65
66 i = 1;
67 printf("factorial(%d) = %d\n", i, factorial(i));
68 i = 2; printf("factorial(%d) = %d\n", i, factorial(i));
69 i = 3; printf("factorial(%d) = %d\n", i,
70 factorial(
71 i));
72
73 i
74 =
75 4;
76 printf(
77 "factorial(%d) = %d\n",
78 i,
79 factorial(i));
80
81 if (i < 5)
82 i = 5;
83 else
(ladebug) process 2
Current Process: localhost:201 (./c_whatis).
(ladebug) show process all
localhost:200 (mp-fork) dead.
> \_localhost:201 (mp-fork->./c_whatis) stopped. 3
(ladebug) next
stopped at [int main(void):63 0x1200013ac]
63 foo();
(ladebug) next
result of foo = 5040
stopped at [int main(void):64 0x1200013bc]
64 baz(x,3,x+1);
(ladebug) next
result of foo = 5040
result of baz = 720
stopped at [int main(void):66 0x1200013dc]
66 i = 1;
(ladebug) next
stopped at [int main(void):67 0x1200013e4]
67 printf("factorial(%d) = %d\n", i, factorial(i));
(ladebug) next
factorial(1) = 1
stopped at [int main(void):68 0x12000141c]
68 i = 2; printf("factorial(%d) = %d\n", i, factorial(i));
(ladebug) next
factorial(2) = 2
stopped at [int main(void):69 0x12000145c]
69 i = 3; printf("factorial(%d) = %d\n", i,
(ladebug) step
stopped at [int factorial(int):8 0x1200011e8]
8 switch (n) {
(ladebug) where
>0 0x1200011e8 in factorial(n=3) c_whatis.c:8
#1 0x120001470 in main() c_whatis.c:69
(ladebug) cont
factorial(3) = 6
factorial(4) = 24
factorial(5) = 120
factorial(6) = 720
factorial(7) = 5040
factorial(8) = 40320
abcdefghij
abcdefghij
Process has exited with status 0
(ladebug) show process all
localhost:200 (mp-fork) dead.
> \_localhost:201 (mp-fork) dead.
(ladebug)