C H A P T E R  10

Fixing and Continuing

Using the fix command lets you recompile edited native source code quickly without stopping the debugging process. You cannot use the fix command to recompile Java code.



Note - The fix command is not available on Linux platforms.



This chapter is organized into the following sections:


Using Fix and Continue

The fix and continue feature lets you modify and recompile a native source file and continue executing without rebuilding the entire program. By updating the .o files and splicing them into your program, you don't need to relink.

The advantages of using fix and continue are:



Note - Do not use the fix command if a build is in process.



How Fix and Continue Operates

Before using the fix command you must edit the source in the editor window. (See Modifying Source Using Fix and Continue for the ways you can modify your code). After saving changes, type fix. For information on the fix command, see fix Command.

Once you have invoked the fix command, dbx calls the compiler with the appropriate compiler options. The modified files are compiled and shared object (.so) files are created. Semantic tests are done by comparing the old and new files.

The new object file is linked to your running process using the runtime linker. If the function on top of the stack is being fixed, the new stopped in function is the beginning of the same line in the new function. All the breakpoints in the old file are moved to the new file.

You can use fix and continue on files that have been compiled with or without debugging information, but there are some limitations in the functionality of the fix command and the cont command for files originally compiled without debugging information. See the -g option description in fix Command for more information.

You can fix shared objects (.so) files, but they must be opened in a special mode. You can use either RTLD_NOW|RTLD_GLOBAL or RTLD_LAZY|RTLD_GLOBAL in the call to the dlopen function.

Modifying Source Using Fix and Continue

You can modify source code in the following ways when using fix and continue:

Problems can occur when functions are mapped from the old file to the new file. To minimize such problems when editing a source file:

If you make any of the above changes, rebuild your entire program rather than using fix and continue.


Fixing Your Program

You can use the fix command to relink source files after you make changes, without recompiling the entire program. You can then continue execution of the program.

To fix your file:

1. Save the changes to your source.

2. Type fix at the dbx prompt.

Although you can do an unlimited number of fixes, if you have done several fixes in a row, consider rebuilding your program. The fix command changes the program image in memory, but not on the disk. As you do more fixes, the memory image gets out of sync with what is on the disk.

The fix command does not make the changes within your executable file, but only changes the .o files and the memory image. Once you have finished debugging a program, you must rebuild your program to merge the changes into the executable. When you quit debugging, a message reminds you to rebuild your program.

If you invoke the fix command with an option other than -a and without a file name argument, only the current modified source file is fixed.

When fix is invoked, the current working directory of the file that was current at the time of compilation is searched before executing the compilation line. There might be problems locating the correct directory due to a change in the file system structure from compilation time to debugging time. To avoid this problem, use the command pathmap, which creates a mapping from one path name to another. Mapping is applied to source paths and object file paths.

Continuing After Fixing

You can continue executing using the cont command (see cont Command).

Before resuming program execution, be aware of the following conditions that determine the effect of your changes.

Changing an Executed Function

If you made changes in a function that has already executed, the changes have no effect until:

If your modifications involve more than simple changes to variables, use the fix command, then the run command. Using the run command is faster because it does not relink the program.

Changing a Function Not Yet Called

If you have made changes in a function not yet called, the changes will be in effect when that function is called.

Changing a Function Currently Being Executed

If you have made changes to the function currently being executed, the impact of the fix command depends on where the change is relative to the stopped in function:

Changing a Function Presently on the Stack

If you have made changes to a function presently on the stack, but not to the stopped in function, the changed code is not used for the present call of that function. When the stopped in function returns, the old versions of the function on the stack are executed.

There are several ways to solve this problem:

If there are breakpoints in modified functions on the stack, the breakpoints are moved to the new versions of the functions. If the old versions are executed, the program does not stop in those functions.


Changing Variables After Fixing

Changes made to global variables are not undone by the pop command or the fix command. To reassign correct values to global variables manually, use the assign command. (See assign Command.)

The following example shows how a simple bug can be fixed. The application gets a segmentation violation in line 6 when trying to dereference a NULL pointer.


dbx[1] list 1,$
	1	#include <stdio.h>
	2	
	3	char *from = "ships";
	4	void copy(char *to)
	5	{
	6		while ((*to++ = *from++) != '\0');
	7		*to = '\0';
	8	}
	9	
	10	main()
	11	{
	12		char buf[100];
	13	
	14		copy(0);
	15		printf("%s\n", buf);
	16		return 0;
	17	}
(dbx) run
Running: testfix
(process id 4842)
signal SEGV (no mapping at the fault address) in copy at line 6 in file "testfix.cc"
	6		while ((*to++ = *from++) != '\0');

Change line 14 to copy to buf instead of 0 and save the file, then do a fix:


	14		copy(buf);  	<=== modified line
(dbx) fix
fixing "testfix.cc" .....
pc moved to "testfix.cc":6
stopped in copy at line 6 in file "testfix.cc"
	6		while ((*to++ = *from++) != '\0')

If the program is continued from here, it still gets a segmentation fault because the zero-pointer is still pushed on the stack. Use the pop command to pop one frame of the stack:


(dbx) pop
stopped in main at line 14 in file "testfix.cc"
      14 copy(buf); 

If the program is continued from here, it runs, but does not print the correct value because the global variable from has already been incremented by one. The program would print hips and not ships. Use the assign command to restore the global variable and then use the cont command. Now the program prints the correct string:


(dbx) assign from = from-1
(dbx) cont
ships


Modifying a Header File

Sometimes it may be necessary to modify a header (.h) file as well as a source file. To be sure that the modified header file is accessed by all source files in the program that include it, you must give as an argument to the fix command a list of all the source files that include that header file. If you do not include the list of source files, only the primary (current) source file is recompiled and only it includes the modified version of the header file. Other source files in the program continue to include the original version of that header file.


Fixing C++ Template Definitions

C++ template definitions cannot be fixed directly. Fix the files with the template instances instead. You can use the -f option to override the date-checking if the template definition file has not changed. For programs compiled with the Sun Studio C compiler, dbx looks for template definition .o files in the default repository directory SunWS_cache. The -ptr compiler option is not supported by the fix command in dbx.