Interpreting Discover Error Messages

In some cases, Discover can report an error that is not actually an
error. Such cases are called false positives. Discover analyzes code at instrumentation time
to reduce the occurrence of false positives compared to similar tools, but there
are cases where they still occur. The following sections provide a few tips
that might help you to identify and possibly avoid false positives in Discover
reports.

Partially Initialized Memory

Bit fields in C and C++ allow you to create compact data
types. For example:

struct my_struct {
unsigned int valid : 1;
char c;
};

In the example, the structure member my_struct.valid takes only one bit in memory.
However, on SPARC platforms, the CPU can modify memory only in bytes, so
the whole byte containing struct.valid must be loaded in order to access or
modify the structure member. Moreover, sometimes the compiler might find it more efficient
to load several bytes (for example, a machine word of four bytes) at
once. When Discover detects such a load, without additional information it assumes that
all four bytes are used. And if, for example, the field my_struct.valid was
initialized, but the field my_struct.c was not, and the machine word containing both fields
was loaded, Discover would flag a partially initialized memory read (PIR).

Another source of false positives is initialization of a bit field. To write
a part of a byte, the compiler must first generate code that
loads the byte. If the byte was not written prior to a read,
the result is an uninitialized memory read error (UMR).

To avoid false positives for bit fields, use the -g option or the
-g0 option when compiling. These options provide extra debugging information to Discover to help
it identify bit field loads and initialization, which will eliminate most false positives.
If you cannot compile with the -g option for some reason, then initialize
structures with a function such as memset(). For example:

Speculative Loads

Sometimes the compiler generates a load from a known memory address under conditions
where the result of the load is not valid on all program paths.
This situation often occurs on SPARC platforms because such a load instruction can
be placed in the delay slot of a branch instruction. For example, here
is a C code fragment:

Assume that in the example, the function foo() returns 0 and does
not initialize i. The load from i is still generated, though not
used. But the load will be seen by Discover, which will report a
load of an uninitialized variable (UMR).

Discover uses dataflow analysis to identify such cases whenever possible, but sometimes they
are impossible to detect.

You can reduce the occurrence of these types of false positives by
compiling with a lower optimization level.

Uninstrumented Code

Sometimes it is not possible for Discover to instrument 100% of your program.
Perhaps some of your code comes from an assembly language source file or
a third-party library that cannot be recompiled and so cannot be instrumented. Discover has
no knowledge of the memory blocks the non-instrumented code is accessing and modifying.
Assume for example that a function from a third-party shared library initializes a
block of memory that is later read by the main (instrumented) program. Since
Discover does not know that the memory has been initialized by the library,
the subsequent read generates an uninitialized memory error (UMR).

To provide a solution for such cases, the Discover API includes the
following functions:

void __ped_memory_write(unsigned long addr, long size, unsigned long pc);
void __ped_memory_read(unsigned long addr, long size, unsigned long pc);
void __ped_memory_copy(unsigned long src, unsigned lond dst, long size, unsigned long pc);

You can call the API functions from your program to inform Discover of
specific events such as a write to a memory area (__ped_memory_write()) or
a read from a memory area (__ped_memory read()). In both cases, the starting address
of the memory area is passed in the addr parameter and its
size is passed in the size parameter. Set the pc parameter to 0.

Use the __ped_memory_copy function to inform Discover of memory that is being copied
from one location to another. The starting address of the source memory is
passed in the src parameter, the starting address of the destination area is
passed in the dst parameter, and the size is passed in the size
parameter. Set the pc parameter to 0.

To use the API, declare these functions in your program as weak.
For example, include the following code fragment in your source code.

The API functions are defined in the internal Discover library, which is linked
with your program at instrumentation time. However, when your program is not instrumented,
this library is not linked and thus all calls to the API functions
will result in application hang-up. So you must disable these functions when you
are not running your program under Discover. Alternatively, you can create a dynamic
library with empty definitions of the API functions and link it with your
program. In this case, when you run your program without Discover, your library
will be used, but when you run it under Discover, the real API
functions will be called automatically.