| www.delorie.com/gnu/docs/gdb/gdbint_119.html | search |
![]() Buy the book! | |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In addition to getting the syntax right, there's the little question of semantics. Some things are done in certain ways in GDB because long experience has shown that the more obvious ways caused various kinds of trouble.
You can't assume the byte order of anything that comes from a target
(including values, object files, and instructions). Such things
must be byte-swapped using SWAP_TARGET_AND_HOST in
GDB, or one of the swap routines defined in `bfd.h',
such as bfd_get_32.
You can't assume that you know what interface is being used to talk to
the target system. All references to the target must go through the
current target_ops vector.
You can't assume that the host and target machines are the same machine (except in the "native" support modules). In particular, you can't assume that the target machine's header files will be available on the host machine. Target code must bring along its own header files -- written from scratch or explicitly donated by their owner, to avoid copyright problems.
Insertion of new #ifdef's will be frowned upon. It's much better
to write the code portably than to conditionalize it for various
systems.
New #ifdef's which test for specific compilers or manufacturers
or operating systems are unacceptable. All #ifdef's should test
for features. The information about which configurations contain which
features should be segregated into the configuration files. Experience
has proven far too often that a feature unique to one particular system
often creeps into other systems; and that a conditional based on some
predefined macro for your current system will become worthless over
time, as new versions of your system come out that behave differently
with regard to this feature.
Adding code that handles specific architectures, operating systems, target interfaces, or hosts, is not acceptable in generic code.
One particularly notorious area where system dependencies tend to creep in is handling of file names. The mainline GDB code assumes Posix semantics of file names: absolute file names begin with a forward slash `/', slashes are used to separate leading directories, case-sensitive file names. These assumptions are not necessarily true on non-Posix systems such as MS-Windows. To avoid system-dependent code where you need to take apart or construct a file name, use the following portable macros:
HAVE_DOS_BASED_FILE_SYSTEM
IS_DIR_SEPARATOR (c)
IS_ABSOLUTE_PATH (file)
FILENAME_CMP (f1, f2)
strcmp; on case-insensitive filesystems it
will call strcasecmp instead.
DIRNAME_SEPARATOR
PATH-style lists, typically held in environment variables.
This character is `:' on Unix, `;' on DOS and Windows.
SLASH_STRING
SLASH_STRING is "/" on most systems, but might be
"\\" for some Windows-based ports.
In addition to using these macros, be sure to use portable library
functions whenever possible. For example, to extract a directory or a
basename part from a file name, use the dirname and
basename library functions (available in libiberty for
platforms which don't provide them), instead of searching for a slash
with strrchr.
Another way to generalize GDB along a particular interface is with an
attribute struct. For example, GDB has been generalized to handle
multiple kinds of remote interfaces--not by #ifdefs everywhere, but
by defining the target_ops structure and having a current target (as
well as a stack of targets below it, for memory references). Whenever
something needs to be done that depends on which remote interface we are
using, a flag in the current target_ops structure is tested (e.g.,
target_has_stack), or a function is called through a pointer in the
current target_ops structure. In this way, when a new remote interface
is added, only one module needs to be touched--the one that actually
implements the new remote interface. Other examples of
attribute-structs are BFD access to multiple kinds of object file
formats, or GDB's access to multiple source languages.
Please avoid duplicating code. For example, in GDB 3.x all
the code interfacing between ptrace and the rest of
GDB was duplicated in `*-dep.c', and so changing
something was very painful. In GDB 4.x, these have all been
consolidated into `infptrace.c'. `infptrace.c' can deal
with variations between systems the same way any system-independent
file would (hooks, #if defined, etc.), and machines which are
radically different don't need to use `infptrace.c' at all.
All debugging code must be controllable using the `set debug
module' command. Do not use printf to print trace
messages. Use fprintf_unfiltered(gdb_stdlog, .... Do not use
#ifdef DEBUG.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
| webmaster donations bookstore | delorie software privacy |
| Copyright © 2003 by The Free Software Foundation | Updated Jun 2003 |