TOC PREV NEXT

Chapter 1
Porting SCO OpenServer 5 Applications
to SCO OpenServer 6


This document describes porting SCO OpenServer Release 5 applications to Release 6, and techniques that can be used to make such a port successful.

1.1 About porting SCO OpenServer 5 applications

Porting applications to SCO OpenServer 6 is not difficult. Many ports will involve no more than making a few changes to a makefile, then recompiling and using the SCO OpenServer 6 Development System (Dev Sys).

Porting may not even be necessary:

But you may want to recompile your application on SCO OpenServer 6 to take advantage of new features such as multithreading or large files, to gain better runtime performance, to access new resources on Release 6, or for other reasons.

The SCO OpenServer 6 Development System allows you to compile programs using either the Release 5 ABI or the Release 6 ABI, as described in the following section.

1.1.1 Compiler ABI modes: UDK and OSR5

SCO OpenServer 6 is designed to run both SCO OpenServer Release 5 (OSR5) ABI applications as well as System V Release 5 (SVR5) applications. These two kinds of applications are distinct because they:

The OSR5 ABI is the interface supported by SCO OpenServer Release 5 systems, while the SVR5 ABI is the default ABI for Release 6 (and for future OpenServer development). It is also the ABI supported by the UnixWare/OpenServer Development Kit (UDK) and so is sometimes called the UDK ABI.

Within any one operating system process, every object file must have been compiled using either the OSR5 ABI or the SVR5 ABI; this applies to the application and all the libraries it uses. These ABIs cannot be mixed within a single process.

The C compiler (cc command), the C++ compiler (CC command), and a few other development tools include a -K option to select the ABI (or mode), with udk representing the SVR5 ABI and osr specifying the OSR5 ABI.

The default ABI used (i.e., when no -K option is specified) depends upon how the compilers and related tools are invoked. For example:
/usr/ccs/bin/cc default is UDK mode; use -K osr for OSR5 mode (OSR5 ABI)
/osr5/usr/ccs/bin/cc default is OSR mode; use -K udk for UDK mode (SVR5 ABI)

In general, which ABI you use when you port your application to Release 6, depend on the considerations listed in the following table:

Use UDK mode if:

Use OSR5 mode if:

  • You are writing a new application, or porting an application that has never been run on an SCO platform.
  • Your application needs to use threads (e.g. makes calls to pthread_create()) or large files (e.g. makes calls to fopen64()) or other advanced features of the Release 6 kernel.
  • You would like your application binary to run on UnixWare as well as SCO OpenServer Release 6.
  • You are writing Java native code (JNI)
  • You are writing a device driver for SCO OpenServer Release 6.
  • You want to minimize code changes to your application and pick up improvements made to the OSR5 APIs, or to generate better-performing code.
  • You are developing an application that will also run on Release 5.
  • Your application needs to link with Release 5 objects or libraries (.o, .a, .so files) that you or others created, that you do not want to (or cannot) recompile.

For more information about using these compiler modes, see the Dev Sys overview at: http://osr600doc.sco.com/en/SDK_oview/DEVSYS.oview.html">http://osr600doc.sco.com/en/SDK_oview/DEVSYS.oview.html.

1.1.2 Mixed mode issues

If you have an existing SCO OpenServer 5 application that you want to modernize with threads or large files or some other SVR5-dependent feature, you must compile it in UDK mode. Because UDK mode features some different APIs from SCO OpenServer 5, it is possible that you will have some porting work and source code modifications to do. Occasionally the mode requirements may present a contradiction: for instance, you have an existing SCO OpenServer 5 application program that depends upon and is linked against a third-party library archive. Now you want to modify another part of this program to handle large files. That means you need to use UDK mode, but the presence of the third-party library means you need to use OSR mode. Assuming you cannot get the library vendor to re-build it in UDK mode, what do you do?

In this situation you must split your application program into two processes. One process makes the calls to the third-party library and is compiled in OSR5 mode. The other process makes the calls to do the large file I/O and is compiled in UDK mode. Then you must use some sort of inter-process mechanism (such as sockets, pipes, or IPC) to communicate between the two processes.

1.2 Tool sets supported

The SCO OpenServer 6 Development System (Dev Sys) is found on SCO OpenServer 6 Installation CD-ROM in the media kit. The Dev Sys offers:

1.4 Compiler option guidelines

Basic compiler options are defined by POSIX and tend to be the same across platforms (such as -c and -P). Others are trickier and can lead to porting problems. Here are some of the more common problems:

Using -lthread will cause problems (and the compiler will generate a warning), because of the system library ordering problem discussed previously.
This means libresolv need not be present, but should go first if it is used. The other two are mandatory and should be used in the order shown.

1.5 API issues

In general, SCO OpenServer 6 is compliant with POSIX, XPG4, UNIX 95, and UNIX 98. If the application being ported is also compliant to these standards, a simple recompile and relink should be all that is necessary. In reality, things are rarely that easy. Kernel and API compatibility issues may affect the ability of your application to run as expected on Release 6. These issues are described in the section "Kernel and API Compatibility Notes" on page 23.

1.6 C language dialect issues

  • Generally, the Dev Sys C compiler accepts any ISO-standard C code. In default mode, this also includes accepting K&R C dialect (but using ISO semantics where there is a difference). You can give those cases K&R semantics using the cc -Xt transition compilation option. This is usually done to preserve "unsigned-preserving" integral promotion rules (versus the standard "value-preserving" integral promotion rules). Do not use cc -Xt unless you must. It is better to bring code up to date since using cc -Xt can result in a significant performance loss (due to the lack of the volatile attribute).
  • Another porting problem occurs for code that assumes a particular signedness of "plain" char. By default, the Dev Sys compiler takes them as signed; the default can be changed to unsigned using the -Kuchar option.
  • The Release 5 Dev Sys C compiler's -Xk option for K&R mode is not supported by the Release 6 Dev Sys C compiler; use -Xt instead. In addition, the OSR5 C compiler's -Xm option for `Microsoft mode' is obsolete and no longer supported.
  • Note that the Dev Sys C compiler fully supports 64-bit integers via the long long type.
  • The most frequent source of C dialect problems comes from gcc-built applications. The GNU C compiler has a number of extensions in it that are not supported on other platforms. The most well-known of these is support for variable-sized arrays:
    
    int length(void); 
    int foo(void) 
    { 
    	int x=length(); 
    	char f[x]; 
    	...
    } 
    
This feature is present in a somewhat different form in the ANSI/ISO 1999 C standard, but is not supported in the Dev Sys C compiler. This means the code must be rewritten using heap allocation.
  • Another change brought about by the C 99 standard is that inline and restrict are now C keywords. If this conflicts with existing code and it is not practical to modify the code, the Dev Sys cc -Xb option can be used to suppress the recognition of these two new keywords.

1.7 C++ language dialect issues

The ANSI/ISO 1998 C++ standard invalidated a lot of old, existing C++ code. The following are a few of the better-known examples:

  • new keywords
  • for loop variable scope change
  • template specialization syntax, guiding declarations
  • template friends syntax change
  • new failure throws exception
  • implicit int gone

A more detailed discussion of some of these incompatibilities can be found in newer C++ textbooks, such as Bjarne Stroustrup's The C++ Programming Language (Third Edition), or in the Internet McCluskey C++ Newsletter.

So how do you get existing C++ code bases to compile using the Dev Sys compiler? For many years the original AT&T cfront was the most heavily used C++ compiler. For existing cfront-built code, there is a Dev Sys CC -Xo compatibility option that provides cfront source compatibility. But this also enables cfront bug tolerance and many anachronisms. There are some instances of cfront that CC -Xo will not detect or accept. It is intended as a transitional tool for converting code to the modern dialect of C++ acceptable by the Dev Sys C++ compiler. It should not be used on a permanent basis.

For example, consider this code:


template <class T> 
class A {
	int m, n;
	int explicit; 
public: 
	void f(); 
	T g(); 
}; 
template <class T> 
void A<T>::f() { 
	for (int i = 0; i < 10; i++) 
		n += i; 
	for (i = 0; i < 10; i++) 
		m += i; 
} 
char A<char>::g() { return `a'; } 
int main() { 
	A<int> a; 
	a.f(); 
} 

This compiles under a cfront-era C++ compiler without problems, but generates many errors with the Dev Sys C++ compiler. The same code source compiles without error under the Dev Sys C++ compiler using the -Xo option.

Most ANSI/ISO source language incompatibilities are not complicated and can be straightforwardly resolved, so in most cases it is best to bring the code up to date. In this case, it's simply a matter of avoiding the new keyword, using the new template specialization syntax, and adjusting to the new for loop variable scope rule.

Here is the new version with three simple edits that compiles properly on the OSR6 Dev Sys C++ compiler without using any compatibility option:


template <class T> 
class A { 
	int m, n; 
	int is_explicit; 							// changed 
public: 
	void f(); 
	T g(); 
}; 
template <class T> 
void A<T>::f() { 
	for (int i = 0; i < 10; i++) 
		n += i; 
	for (int i = 0; i < 10; i++) 					// changed 
		m += i; 
} 
template<> char A<char>::g() { return `a'; } 					// changed 
int main() { 
	A<int> a; 
	a.f(); 
} 

1.8 Changes to the runtime environment

The subsections that follow discuss changes to the runtime environment in SCO OpenServer Release 6 that must be taken into account when porting any Release 5 application. Your application may also encounter runtime issues related to other changes in the runtime environment between Release 5 and Release 6. See the Upgrade Guide at http://www.sco.com/support/docs/openserver/600/migration for more information on changes to the runtime environment in Release 6.

Note: While the SVR5 ABI is the default runtime binary interface, the SVR5 kernel recognizes OSR5 ABI applications and runs them in the environment that OSR5 ABI applications expect. There are no special steps or commands needed to run an application on Release 6 that was compiled using OSR5 mode (or compiled on Release 5).

1.8.1 Runtime commands

If a Release 5 application requires Release 5 runtime commands (that is, it fails using the default command reached by the default PATH variable on OpenServer 6), Release 5 commands are supplied in the directory /osr5/bin. Change the PATH variable for the application so that it accesses binaries under /osr5/bin before other command directories. Note that manpages for these commands are not provided on the system; access them on the OpenServer 507 doc web site: http://osr507doc.sco.com">http://osr507doc.sco.com.

1.8.2 Runtime access of system/data files

Although links have been used to minimize problems associated with changes of location of system files accessed by applications at runtime, some applications that depend on the internal format of files may experience problems interpreting file contents. One example is the default /bin/cpio command, which uses an "Extended cpio File Format", instead of the "ASCII cpio format" used by the cpio command on OpenServer 5. If your application requires the OpenServer 5 cpio file format, then you'll need to change your application to access the /osr5/bin/cpio version of cpio as described in the last section.

1.8.3 NETbios/NETbeui

NETbios/NETbeui are no longer supported; runtime calls to NETbios commands and references to NETbios resources will fail on SCO OpenServer Release 6.

1.8.4 XENIX 286 emulators

Calls to the legacy i286emul/x286emul runtime emulators and references to associated resources will fail on OpenServer 6.

1.9 Binary debugging

SCO OpenServer Release 6 includes a number of tools for debugging. The sections that follow discuss some of these features in more detail.

debug

Powerful and effective tool for source- and assembly-language debugging. Replaces dbx, dbXtra, and other OpenServer 5 debuggers. Offers both graphical and command-line user interfaces. Full support for both C and C++. Full support for multi-process and multi-thread debugging. Available in both UDK and OSR5 modes (multi-thread does not apply to OSR mode).

fprof

Flow profiling to analyze performance and locality of reference of text. Only available in UDK mode, but similar functions are available with fur.

fur

Object-level optimizer that uses dynamic feedback from flow profiling to transparently rearrange application object code for better performance. Available in both UDK and OSR5 modes.

While fprof is not available in OSR5 mode, fur can perform instrumentation and flow analysis at the code block level. Based on the flow through each function, fur can reorder the object code in a function to:

  • improve reference locality
  • reduce instruction execution stalls
  • reduce branching
  • improve cache hits

as well as reorder functions within an object.

memtool

Memory error detection tool that finds common C or C++ memory errors and leaks and gives source-level information about them. Only available in UDK mode.

1.9.1 Tracing system calls with truss

SCO OpenServer 6 includes a useful command named truss that can trace the system calls made by an application. Using truss does not require recompilation, relinking, access to the source code, or even a symbol table. The truss command replaces the Release 5 trace and scotruss commands.

Consider this code:


$ cat fstab.c 
#include <stdio.h> 
int main() { 
	FILE* fp = fopen("/etc/fstab", "r"); 
	if (!fp) 
		fprintf(stderr, "*** cannot open file\n"); 
	fclose(fp); 
} 
$ cc fstab.c 
$ ./a.out 
*** cannot open file 

SCO OpenServer 6

The program fails because SCO OpenServer 6 uses /etc/vfstab not /etc/fstab, but the error message does not indicate the file it failed to open. Running the program through truss displays each system call, along with its arguments and the return code:


$ truss ./a.out 
execve("./a.out", 0x08047570, 0x08047578) argc = 1 
open("/etc/fstab", O_RDONLY, 0666) Err#2 
ENOENT 
*** cannot open file 
write(2, " * * * c a n n o t  o".., 21) = 21 
_exit(-1) 

In a large program (especially one you are not that familiar with), truss can help you determine the point of failure. Using the -f option, truss can follow child processes as well as the parent process. You can also use truss to grab and release existing processes on the system.

Along with knowing symbolic names for many manifest constants (the O_RDONLY above, for example), truss can display additional information to further focus the trace. An explicit list of system calls to trace (or not to trace) can be given to truss with the -t option.

The -a and -e options respectively cause truss to display all the passed arguments and the entire environment at an exec.

Another advantage is that truss knows structures that cross the system call boundary. Using the -v option, you can specify system calls for which you want to see complete structures displayed.

Finally, all of the data read and/or written on a file descriptor (instead of the default first few bytes) can be displayed using the -r and/or -w options.


$ truss -w2 ./a.out 
execve("./a.out", 0x08047570, 0x08047578) argc = 1 
open("/etc/fstab", O_RDONLY, 0666) Err#2 
ENOENT 
*** cannot open file 
write(2, 0x08047C14, 21) = 21 
     * * * c a n n o t  o p e n  f i l e\n 
_exit(-1) 

Note that you must be root to run truss on privileged programs.

1.9.2 Using the dynamic library tracing feature of the runtime linker

A feature similar to truss is provided for dynamic executables by the runtime linker in SCO OpenServer 6.

When a dynamic executable calls a function that (potentially) is defined elsewhere -- outside of the calling shared library or executable -- a call is actually made to a bit of code in the "procedure linkage table" (PLT). This code then does an indirect branch to the target function. But, at process startup (by default), all the PLT entries end up branching to the runtime linker, which searches the executable and the current set of shared libraries for the actual definition of the target function. Once found, the runtime linker modifies the destination of the indirect branch for that PLT entry so that it jumps to the actual function.

Dynamic library tracing takes advantage of this lookup process and interposes a reporting function between the caller and the callee. It can also insert a bit of code to return to that comes between the callee and the caller that similarly reports the return value of the function.

As with truss, dynamic library tracing is disabled for processes that gain privilege for obvious security reasons.

This tracing differs from truss in a number of ways:

  • Because each function can call further functions, the call and return are displayed separately.
  • The runtime linker only knows a name to search for and (when found) the address. It does not inherently understand anything else about a function, while truss has knowledge of each system call. However, if the defining library provides a special table of encoded bits with an entry for this function, the reporting code will be able to do something other than just print a few hexadecimal words that might be actual arguments. Only the C and threads libraries provide this table. (Note that if an entry is found, the reporting code can cause the process to die if it attempts to dereference a bad string pointer.)
  • The runtime linker can only report functions that go through its lookup processing (internal function calls are not reported).
  • The reporting code also displays the caller of each function.

Dynamic library tracing is enabled by running a process with certain environment variables set:

LD_TRACE

Without LD_TRACE in the environment, no reporting will occur. If it exists but has an empty string value, lines of this form are displayed:


sym(arg1,arg2,arg3) from hex_addr

For unknown functions, three hexadecimal words are printed as arguments. Otherwise, the value of LD_TRACE is expected to be one or more comma-separated keywords from the following list:

  • sym -- display name+offset instead of hex_addr. The +offset part is only shown when nonzero.
  • lib -- add @lib after a hex_addr or name+offset to give the containing library (or executable).
  • ret -- also include tracing function returns.
  • tim -- add a at sec.usec.
  • hitim -- add either a at ticks or, when LD_TRACE_SCALE is set, at sec.ticks. Note that the high-resolution timer requires the Pentium rdtsc instruction. Moreover, using this instruction is a privileged operation by default.

To enable this feature in SCO OpenServer 6, you must set USER_RDTSC to nonzero using idtune and rebuild and reboot. Finally, because we do not synchronize the processor timers on multiple CPU boxes, the timings are likely to be inaccurate for such systems.

LD_TRACE_FILENO

Provides the file descriptor to which to write the reports. By default, it is 2 (standard error).

LD_TRACE_ARGNO

Provides the number of hexadecimal words to display for unknown functions. It is 3 by default.

LD_TRACE_SCALE

Provides the clock speed in MHZ to be used with hitim.

LD_TRACE_STACK

Provides a simple stack trace feature. Its value is expected to be a comma-separated list of function names for which to display a stack trace at each call. All other reporting is disabled when LD_TRACE_STACK is set. The stack trace algorithm uses a fairly straightforward scheme which, unfortunately, fails for functions that return structures.

LD_TRACE_FRAMES

Provides a maximum stack depth to trace when LD_TRACE_STACK is set. The default value is zero which is taken to mean the entire stack.

LD_TRACE_ROUTINE
LD_TRACE_LIBRARY

Provide comma-separated lists of specific routine names and library names, respectively, to report. Both of these interpret a leading "!" as inverting the list (all but ...). Note that LD_TRACE_STACK wins over LD_TRACE_ROUTINE. These two variables can be used to greatly trim down the large amount of noise generated by default with LD_TRACE.

LD_TRACE_MAXSTR

Sets the limit on string printing to a value in the range [0,120], with the default being 20. (A value of 0 disables the dereferencing, which may be necessary when a bad pointer has been passed to a routine that RTLD expects to display as a string.)

Tracing the same fstab.c example from above:


$ LD_TRACE=sym 
./a.out 
atexit(0x80483b4) from 0x8048459 
atexit(0xbff9b09c) from 0x8048465 
atexit(0x8048514) from 0x804846f 
__fpstart() from 0x804847b 
fopen("/etc/fstab","r") from 0x80484b1 
_findiop() from _realfopen+7 
_open("/etc/fstab",0x0,0x1b6) from endopen+141 
__thr_errno() from _cerror+29 
fprintf(0x80495ec,"*** cannot open 
file"...,0x0,0x8047cb8,0x8048485) from 0x80484cc 
_findbuf(0x80495ec) from fprintf+116 
_xflsbuf(0x8047c44) from _idoprnt+358 
_write(2,0x8047c04,21) from _xflsbuf+89 
*** cannot open file 
fclose(0x0) from 0x80484d7 
exit(-1) from 0x804848e 
_exithandle() from exit+18 
_setjmp(0xbfffe628) from _exithandle+100 
_cleanup() from _exithandle+151 
fflush(0x0) from _cleanup+9 

Note that even with symbols enabled, the reporting of some addresses (like the caller of fopen) is still just a hexadecimal value. This is because the only names available to the reporting code are those exported from the executable and shared libraries and by default only the necessary few global names are exported by the linker in the executable. If you use pass the -Wl,-Bexport option to the linker (see above regarding exported names) all global functions are exported.

Adding return value tracing:


$ LD_TRACE=sym,ret ./a.out 
atexit(0x80483b4) from 0x8048459 
	=> atexit returned 0 
atexit(0xbff9b09c) from 0x8048465 
	=> atexit returned 0 
atexit(0x8048514) from 0x804846f 
	=> atexit returned 0 
__fpstart() from 0x804847b 
	=> __fpstart returned 
fopen("/etc/fstab","r") from 0x80484b1 
_findiop() from _realfopen+7 
	=> _findiop returned 0x80496d0 
_open("/etc/fstab",0x0,0x1b6) from endopen+141 
__thr_errno() from _cerror+29 
	=> __thr_errno returned 0xbfffedd0 
	=> _open returned -1 
	=> fopen returned 0x0 
fprintf(0x80495ec,"*** cannot open 
file"...,0x0,0x8047cb8,0x8048485) from 0x80484cc 
_findbuf(0x80495ec) from fprintf+116 
	=> _findbuf returned 0x80495ec 
_xflsbuf(0x8047c44) from _idoprnt+358 
_write(2,0x8047c04,21) from _xflsbuf+89 
*** cannot open file 
	=> _write returned 21 
	=> _xflsbuf returned 0 
	=> fprintf returned 21 
fclose(0x0) from 0x80484d7 
	=> fclose returned -1 
exit(-1) from 0x804848e 
_exithandle() from exit+18 
_setjmp(0xbfffe628) from _exithandle+100 
_cleanup() from _exithandle+151 
fflush(0x0) from _cleanup+9 
	=> fflush returned 0 
	=> _cleanup returned 
	=> _exithandle returned 

Note in this example that the return from setjmp is not displayed. Certain special functions like setjmp are sensitive to their return address. Finally, a stack trace for write results in the following:


$ LD_TRACE=sym LD_TRACE_STACK=_write 
./a.out 
[0] _write(2,0x8047bec,21) 
[1] _xflsbuf+89(0x8047c2c) [0xbffa7b05] 
[2] _idoprnt+358(0x8047c2c,0x80484f8,0x8047c88) [0xbffa1eb6] 
[3] fprintf+201(0x80495ec,"*** cannot open 
file"...,0x0,0x8047ca0,0x8048485) [0xbffa8195] 
[4] 0x80484cc(0x1,0x8047cac,0x8047cb4) 
Page 41 SCO OpenServer 6 
[5] 0x80484cc(0x8047cac,0x8047cb4,0x0) 
*** cannot open file 

1.9.3 Memory debugging with memtool

C (and to some degree C++) programs are infamous for memory allocation/corruption problems that are difficult to debug. These can sometimes show up during ports of "working" code because a malloc/free mistake might be missed on one platform but not on another. Such problems can go undetected for some time. Commercial tools such as Purify can help track down such problems.

The Dev Sys has a similar tool created by SCO, called memtool. Consider this simple error-ridden program:


1 #include <stdlib.h> 
2 #include <stdio.h> 
3 #include <string.h> 
4 
5 int main() { 
6 	char *p = malloc(7), *q = "yes, too long\n"; 
7 	strcpy(p, q); 
8 	free(p); 
9 	q = 0; 
10 	*p = `Y'; 
11 	realloc(p, 3); 
12 	fputs(p, stderr); 
13 	return *q; 
14 } 

Most of the time, this program will run without problems, but will occassionally fail with memory allocation errors. memtool can be used to pinpoint the code in your application that may cause memory-allocation-related problems. If you take the same program as above and recompile it with -g for maximum symbolic information, you can then run the executable using memtool. This produces the following diagnostic output:


$ cc -g error.c 
$ /usr/ccs/bin/memtool ./a.out 
==============================================================================
Some abuses or potential misuses of the dynamic memory allocation subsystem
have been detected.  The following multiline diagnostics are descriptions
of what exactly has been seen.  They may include use of terms and concepts
with which you may be unfamiliar.  Use the "-v" option to get the complete
version of this introduction.
==============================================================================
A block's spare bytes have been modified.  This usually occurs due to
writing beyond the block's regular bytes, either because an insufficient
number of bytes were requested when the block was allocated or simply
due to a programming logic error.

History for block at address 0x8049b70:
*Stack trace when detected:
  [0] free(ptr=0x8049b70)
  [1] main(0x1,0x8047e24,0x8047e2c) [error.c@8] in ./a.out
  [2] _start() [0x80485f4] in ./a.out

*Stack trace when block at 0x8049b70 was allocated:
  [0] malloc(sz=7)
  [1] main() [error.c@6] in ./a.out
  [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out

Annotated snapshot surrounding the live allocation at address 0x8049b70
when the 5 bytes [0x8049b77,0x8049b7b] were found to have been modified.
This allocation holds 7 byte(s) followed by 5 extra (or spare) byte(s),
and, in this case, spare bytes were found to have been modified.

0x8049b60: 0x00000000 0x00000000 0x00000000 0x00000011  ................
         :                                    ********              ****
0x8049b70: 0x2c736579 0x6f6f7420 0x6e6f6c20 0x00000a67  yes, too long...
         :   --------   ^^------   ^^^^^^^^             -------^^^^^    

==============================================================================
A block's header has been modified.  Often this occurs due to mistakenly
writing past the end of the preceding block.  You might also try using the
"-x" option to add spare bytes to the end of each block, and see whether
your application behaves differently.

History for block at address 0x8049b80:
*Stack trace when detected:
  [0] free(ptr=0x8049b70)
  [1] main(0x1,0x8047e24,0x8047e2c) [error.c@8] in ./a.out
  [2] _start() [0x80485f4] in ./a.out

Annotated snapshot surrounding the live allocation at address 0x8049b80
when the 4 bytes [0x8049b7c,0x8049b7f] were found to have been modified.
This allocation holds 4 bytes, but, in this case, the allocation's
header was found to have been modified.

0x8049b70: 0x2c736579 0xca6f7420 0xcacacaca 0x00000a67  yes, to.....g...
         :                                    ^^^^^^^^              ^^^^
0x8049b80: 0x00000000 0x00000015 0xcacacaca 0xcacacaca  ................
         :   --------                                   ----            

==============================================================================
A recently free()d block was passed as the first argument to realloc().
Only null pointers or live block addresses are permitted to be passed to
realloc(), although, in this implementation, were dynamic memory checking
not enabled, this block's contents would have been preserved between its
being freed and this call to realloc(), but this is a nonportable feature
of this implementation which should not be relied on.

History for block at address 0x8049b70:
*Stack trace when detected:
  [0] realloc(ptr=0x8049b70,sz=3)
  [1] main(0x1,0x8047e24,0x8047e2c) [error.c@11] in ./a.out
  [2] _start() [0x80485f4] in ./a.out

*Stack trace when block at 0x8049b70 was released:
  [0] free(ptr=0x8049b70)
  [1] main() [error.c@8] in ./a.out
  [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out

*Stack trace when block at 0x8049b70 was allocated:
  [0] malloc(sz=7)
  [1] main() [error.c@6] in ./a.out
  [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out

==============================================================================
A free()d block has been modified.  This usually means that the block was
passed to free() or realloc(), but the block continued to be used by your
application, possibly far removed from the deallocating code.

History for block at address 0x8049b70:
*Stack trace when detected:
  [0] realloc(ptr=0x8049b70,sz=3)
  [1] main(0x1,0x8047e24,0x8047e2c) [error.c@11] in ./a.out
  [2] _start() [0x80485f4] in ./a.out

*Stack trace when block at 0x8049b70 was released:
  [0] free(ptr=0x8049b70)
  [1] main() [error.c@8] in ./a.out
  [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out

*Stack trace when block at 0x8049b70 was allocated:
  [0] malloc(sz=7)
  [1] main() [error.c@6] in ./a.out
  [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out

Annotated snapshot surrounding the free allocation at address 0x8049b70
when the byte at 0x8049b70 was found to have been modified.  This
allocation holds 12 bytes, one of which was found to have been modified.

0x8049b60: 0x00000000 0x00000000 0x00000000 0x00000011  ................
         :                                    ********              ****
0x8049b70: 0xcacaca59 0xcacacaca 0xcacacaca 0x00000179  Y...........y...
         :   ------^^   --------   --------             ^-----------    

==============================================================================
		LIVE ALLOCATIONS AT PROCESS EXIT
==============================================================================
Memory allocations that have not been released by the time your process is
finished are in no way an error, but they are potentially ``leaks'' --
allocations that inadvertently have not been released once they were no
longer needed or in use.  If your application has more than a few live
allocations displayed below with the same size and/or were allocated at the
same location, you may well have a leak; or if your application, when run
with more data or for longer periods, displays more live allocations here,
you also may have a leak.  A leak also need not be repaired:  A short-lived
process can easily survive having many leaks, as long as they are not too
large and there are not so many that available memory resources could become
exhausted (or even strained).  Moreover, it may well be that ``the leaks''
are allocations that were all in use up to just before the process exits,
and the effort and the expense to release them all is not warranted.


Stack trace for 4 byte block at 0x8049cf8:
  [0] realloc(ptr=0x8049b70,sz=3)
  [1] main() [error.c@11] in ./a.out
  [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out

*Stack trace for block previously at 0x8049b70 before realloc() to 0x8049cf8:
  [0] free(ptr=0x8049b70)
  [1] main() [error.c@8] in ./a.out
  [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out

1.9.4 Source debugging with debug

The Dev Sys debugger, debug, is a powerful tool for source and assembly-level debugging. It supports both C and C++ language debugging. (For Java debugging, use the command-line jdb debugger.) The debugger has two basic user interfaces: command line and graphical.

Debugging the port of an existing application can be different from program development. Some debugger features that may be useful in this regard are:

  • The map command is excellent at showing the layout of memory, and where any arbitrary address might be.
  • Multithreaded debugging and multiprocess debugging support is strong in the debugger. Many commands take a -p process-nbr.thread-nbr argument indicating a specific process or thread, with -p all applying to all processes or threads.
  • You can follow program forks into both the parent and child processes; other debuggers only allow one or the other.
  • The debugger allows you to grab existing processes (for example, that are hung in loops) or debug core dumps.

The debug tool is not related to the dbx and gdb debuggers many Release 5 users are familiar with, and uses a different command syntax. However, there is "A Guide to debug for dbx Users" on page 63 that will help such users gain familiarity with debug.

For more information on the Dev Sys debugger, see the Dev Sys debug documentation, on the web at http://osr600doc.sco.com/en/SDK_cdebug/CONTENTS.html">http://osr600doc.sco.com/en/SDK_cdebug/CONTENTS.html.

1.10 Development System documentation

See the SCO OpenServer 6 Development System Documentation on the web at http://osr600doc.sco.com/en/Navpages/SDKhome.html. If you installed the Development System on your OpenServer 6 system, the documentation is also available locally at http://hostname:8457/en/Navpages/SDKhome.html, where hostname is the name of your system or localhost.


TOC PREV NEXT