Known bugs in GCC ----------------- Inlining: There is a known bug in GCC when performing function inlining (-finline-functions or -O3) and the function that is being inlined uses a union containing an unsigned 64-bit type and two unsigned 32-bit types, ie a union like this: union { unsigned long long value; struct { unsigned long low; unsigned long high; } s; } Under these circumstances, if the values in the union are constants rather than variables then the function code inliner can mislead the constant expression evaluator inside the compiler so that it incorrectly collapses the constant expressions. Workarounds for this problem are to compile with the -fno-inline-functions switch, or to put the constants into variables, so that the compiler cannot try to simplify the expressions. Variable arguements: There is a known bug in GCC's handling of code which passes a variable sized array as an unnamed argument to a vararg function. ie code like this: extern void foo (int, ...); void bar (int len) { int array[len]; foo (len, array); } In cases like this, gcc will compute the wrong stack address for the variadic argument when it is being handled inside foo(). This means that foo() will see the wrong values for array[]. The workaround is to not pass variable sized arrays to variadic functions. Optimizer Bug: There is a bug in gcc that causes the optimizer to lose track of which registers need to be saved, which seems to occur when all of the following are true for a given function: * The user uses the "register" and "asm" keywords to assign a variable to the frame pointer ($a3). * The frame pointer is not used for anything else. * The function is compiled with -O3. * The frame pointer needs to be preserved due to that variable being possibly modified. In this case, gcc will not save $a3 on entry, but will attempt to restore it on exit, causing a stack inconsistency. The workaround is to use -O2 to compile these functions. So far, the only case we've found that presents this scenario is the syscall definitions. Since they are only compiled as part of glibc, and we've changed the glibc spec to always use -O2, user applications should not normally see this problem. Nested functions: The GCC compiler supports an extension to the C programming language in the form of nested functions. These are functions which are defined inside other functions. This can be useful for modular programming but they are very complicated to handle properly, especially when the code takes the address of a nested function. In order to support nested functions it is necessary for the compiler to create code which will place machine instructions on the execution stack. When the nested function is accessed these instructions are used to jump to the correct place and then to correctly return to the caller once the nested function has finished. Unfortunately placing executable machine instructions on the stack does not always work when the target architecture uses an instruction cache and/or a data cache. This is the case for the MN10300 and AM33, and so GCC's support for this (unofficial) language extension does not work. Debugging Shared Libraries on a Remote Target with GDB ------------------------------------------------------ Using GDB to debug programs which make use of shared libraries should be largely automatic. I.e, during the course of debugging, no user intervention should normally be required to cause a shared library's symbol table to be loaded and correctly relocated. GDB will detect when the remote target has loaded a new shared library and will attempt to load a a copy of that library using a location (path) on the host's filesystem. Since the target's shared library machinery specifies paths which may only make sense on the target, GDB needs a mechanism for translating the target specific paths into paths which are usable on the host (since it is from the host that GDB loads the symbols associated with a shared library). GDB has two variables that may be set to cause this to happen. These are: - solib-absolute-prefix - solib-search-path The string associated with ``solib-absolute-prefix'' is prepended to the target specific path to form a host-specific path. So, e.g, if ``solib-absolute-prefix'' has been set to "/path/to/target-fs-root" and GDB is attempting to load the symbols associated with /lib/libc.so, prepending the value of ``solib-absolute-prefix'' yields "/path/to/target-fs-root/lib/libc.so". GDB uses this path on the host system to (attempt to) load libc.so's symbols. If GDB fails to load the shared library's symbols by prepending ``solib-absolute-prefix'', it will strip off the directory specific components from the path (yielding the shared library's basename) and then prepend each of the paths found in the colon-separated ``solib-search-patch'' variable, stopping on the first one that it successfully opens. ``solib-absolute-prefix'' is normally used in conjunction with "system" libraries such as those found in /lib, /usr/lib, and other "standard" locations for libraries. If the shared library machinery communicates an absolute path for a library to GDB, it is usually best to have a directory on the host which is populated with the libraries found on the target, taking care to preserve the directory structure associated with those libraries. E.g, suppose you had the following three libraries on the target: /lib/libc.so /usr/lib/libdb.so /usr/local/lib/libmp3lame.so Then, on the host, you might have the following isomorphic structure: /path/to/target-fs-root/lib/libc.so /path/to/target-fs-root/usr/lib/libdb.so /path/to/target-fs-root/usr/local/lib/libmp3lame.so In GDB (or in a .gdbinit file), you'd do: set solib-absolute-prefix /path/to/target-fs-root ``solib-relative-path'' is normally used to locate application specific libraries whose paths are specified to GDB as relative paths. It is critical that the libraries on the target are kept in sync with those on the host. If there's a mismatch, i.e, if the target contains a newer version of a library than the host, or vice versa, then strange errors may occur. E.g, it's possible to see an illegal instruction exception, segmentation fault, or other memory related fault on the target due to a breakpoint being placed at incorrect locations. The debugging of multi-threaded programs almost always requires that the shared library machinery is working correctly, so if you're having trouble debugging a multi-threaded program, a good place to start diagnosing the problem is to make sure that ``solib-absolute-prefix'' and ``solib-absolute-path'' are set correctly and that the contents of the libraries on the target match the contents of the corresponding host-located libraries exactly. Known Bugs in Multithread Debugging ----------------------------------- Debugging of multithreaded programs using RDA can be slow for some operations (such as "info thread"), but will complete given enough time. Running the following GDB command will avoid remote protocol timeouts on some operations: set remotetimeout 60 The value provided to remotetimeout may be increased or decreased as desired. In some instances, issuing a "next" command while debugging a thread will not always complete as expected. Debugging with debuginfo files ------------------------------ GDB will automatically use separate debug files under either of the following circumstances: 1. The debug files are placed in the same directory as the libraries to be debugged. 2. The debug files are in a subdirectory, named .debug, of the directory containing the libraries.