RFC: support debug info in separate files

Jim Blandy
2002-11-26T04:27:43Z

This patch, written by Alexander Larsson, allows GDB to use debug info
that has been extracted into a separate executable file, using the
"strip -f" command as provided in Ulrich Drepper's elfutils. This
allows a distribution to provide debug info in separate packages from
the executables it describes.

If you've got all the previous patches I've posted (and if I haven't
botched anything), this should cause no test suite regressions, and
the results of running the test suite both with and without separated
debug info are identical. Starting with current GDB sources, the
other patches you need are:

RFA: testsuite: pass optimization flag in the proper way
RFA: testsuite: attach.exp: don't move executables to /tmp
Re: RFC: allow syms_from_objfile to take a section offset table directly
RFC: Allow symbol_file_add to take section_offsets table

To run the GDB test suite against executables with separated debug info,
see: http://sources.redhat.com/ml/gdb/2002-11/msg00202.html
and: http://sources.redhat.com/ml/gdb/2002-11/msg00215.html

(Note: there is a bug in the elfutils strip that causes some stripped
executables to crash. This has been fixed only very recently, so
you'll need a bleeding-edge version of elfutils, or else you'll get
failures in try_catch.exp due to the inferior crashing.)

If folks don't have concerns about this, I'll commit it on Fri Dec 6.

2002-11-25 Alexander Larsson <alexl@redhat.com>
Jim Blandy <jimb@redhat.com>

Add support for executables whose debug info has been separated
out into a separate file, leaving only a link behind.
* objfiles.h (struct objfile): New fields: separate_debug_objfile
and separate_debug_objfile_backlink.
(put_objfile_before): New declaration.
* symfile.c (symbol_file_add_with_addrs_or_offsets): If this
objfile has its debug info in a separate file, read that,
too. Save the addrs argument, so we can use it again to read the
separated debug info; syms_from_objfile modifies the table we pass
it.
(reread_symbols): After re-reading an objfile, call
reread_separate_symbols to refresh its separate debug info
objfile, if it has one.
(reread_separate_symbols, find_separate_debug_file,
get_debug_link_info, separate_debug_file_exists): New functions.
(debug_file_directory): New global var.
(_initialize_symfile): Initialize debug_file_directory, and
provide the new `set debug-file-directory' command to let the user
change it.
* objfiles.c (free_objfile): If this objfile has its debug info in
a separate objfile, free that one too. If this is itself a
separate debug info objfile, clear our parent's backlink.
(put_objfile_before): New function.
* utils.c (calc_crc32): New function.
* defs.h (calc_crc32): New declaration.
* configure.in: Handle --with-separate-debug-dir config option.
* acinclude.m4 (AC_DEFINE_DIR): New macro.
* acconfig.h (DEBUGDIR): New macro.
* configure, aclocal.m4, config.in: Regenerated.

Index: gdb/acconfig.h
===================================================================
RCS file: /cvs/src/src/gdb/acconfig.h,v
retrieving revision 1.18
diff -u -r1.18 acconfig.h
--- gdb/acconfig.h 11 Apr 2002 18:32:51 -0000 1.18
+++ gdb/acconfig.h 26 Nov 2002 03:42:20 -0000
@@ -176,3 +176,7 @@

/* nativefile */
#undef GDB_NM_FILE
+
+/* debugdir */
+#undef DEBUGDIR
+
Index: gdb/acinclude.m4
===================================================================
RCS file: /cvs/src/src/gdb/acinclude.m4,v
retrieving revision 1.4
diff -u -r1.4 acinclude.m4
--- gdb/acinclude.m4 20 Sep 2002 00:24:01 -0000 1.4
+++ gdb/acinclude.m4 26 Nov 2002 03:42:20 -0000
@@ -1044,3 +1044,18 @@
fi
AC_SUBST(LIBICONV)
])
+
+dnl written by Guido Draheim <guidod@gmx.de>, original by Alexandre Oliva
+dnl Version 1.3 (2001/03/02)
+dnl source http://www.gnu.org/software/ac-archive/Miscellaneous/ac_define_dir.html
+
+AC_DEFUN([AC_DEFINE_DIR], [
+ test "x$prefix" = xNONE && prefix="$ac_default_prefix"
+ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+ ac_define_dir=`eval echo [$]$2`
+ ac_define_dir=`eval echo [$]ac_define_dir`
+ ifelse($3, ,
+ AC_DEFINE_UNQUOTED($1, "$ac_define_dir"),
+ AC_DEFINE_UNQUOTED($1, "$ac_define_dir", $3))
+])
+
Index: gdb/configure.in
===================================================================
RCS file: /cvs/src/src/gdb/configure.in,v
retrieving revision 1.93
diff -u -r1.93 configure.in
--- gdb/configure.in 12 Nov 2002 02:39:41 -0000 1.93
+++ gdb/configure.in 26 Nov 2002 03:42:25 -0000
@@ -237,6 +237,14 @@
AC_CHECK_LIB(socket, socketpair)
AC_CHECK_FUNCS(socketpair)

+debugdir=${libdir}/debug
+
+AC_ARG_WITH(separate-debug-dir,
+[ --with-separate-debug-dir=path Look for global separate debug info in this path [LIBDIR/debug]],
+[debugdir="${withval}"])
+
+AC_DEFINE_DIR(DEBUGDIR, debugdir)
+#AC_DEFINE_UNQUOTED(DEBUGDIR, "$debugdir"),

BFD_NEED_DECLARATION(malloc)
BFD_NEED_DECLARATION(realloc)
Index: gdb/defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.102
diff -u -r1.102 defs.h
--- gdb/defs.h 15 Oct 2002 02:16:51 -0000 1.102
+++ gdb/defs.h 26 Nov 2002 03:42:26 -0000
@@ -382,6 +382,9 @@
extern char *gdb_realpath (const char *);
extern char *xfullpath (const char *);

+extern unsigned long calc_crc32 (unsigned long crc,
+ unsigned char *buf, size_t len);
+
/* From demangle.c */

extern void set_demangling_style (char *);
Index: gdb/objfiles.c
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.c,v
retrieving revision 1.22
diff -u -r1.22 objfiles.c
--- gdb/objfiles.c 29 Jul 2002 22:55:26 -0000 1.22
+++ gdb/objfiles.c 26 Nov 2002 03:42:27 -0000
@@ -333,6 +333,30 @@
return (objfile);
}

+/* Put one object file before a specified on in the global list.
+ This can be used to make sure an object file is destroyed before
+ another when using ALL_OBJFILES_SAFE to free all objfiles. */
+void
+put_objfile_before (struct objfile *objfile, struct objfile *before_this)
+{
+ struct objfile **objp;
+
+ unlink_objfile (objfile);
+
+ for (objp = &object_files; *objp != NULL; objp = &((*objp)->next))
+ {
+ if (*objp == before_this)
+ {
+ objfile->next = *objp;
+ *objp = objfile;
+ return;
+ }
+ }
+
+ internal_error (__FILE__, __LINE__,
+ "put_objfile_before: before objfile not in list");
+}
+
/* Put OBJFILE at the front of the list. */

void
@@ -405,6 +429,18 @@
void
free_objfile (struct objfile *objfile)
{
+ if (objfile->separate_debug_objfile)
+ {
+ free_objfile (objfile->separate_debug_objfile);
+ }
+
+ if (objfile->separate_debug_objfile_backlink)
+ {
+ /* We freed the separate debug file, make sure the base objfile
+ doesn't reference it. */
+ objfile->separate_debug_objfile_backlink->separate_debug_objfile = NULL;
+ }
+
/* First do any symbol file specific actions required when we are
finished with a particular symbol file. Note that if the objfile
is using reusable symbol information (via mmalloc) then each of
Index: gdb/objfiles.h
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.h,v
retrieving revision 1.15
diff -u -r1.15 objfiles.h
--- gdb/objfiles.h 5 Aug 2002 16:17:41 -0000 1.15
+++ gdb/objfiles.h 26 Nov 2002 03:42:27 -0000
@@ -414,6 +414,15 @@
ExportEntry *export_list;
int export_list_size;

+ /* Link to objfile that contains the debug symbols for this one.
+ One is loaded if this file has an debug link to an existing
+ debug file with the right checksum */
+ struct objfile *separate_debug_objfile;
+
+ /* If this is a separate debug object, this is used as a link to the
+ actual executable objfile. */
+ struct objfile *separate_debug_objfile_backlink;
+
/* Place to stash various statistics about this objfile */
OBJSTATS;
};
@@ -504,6 +513,8 @@
extern struct objfile *allocate_objfile (bfd *, int);

extern int build_objfile_section_table (struct objfile *);
+
+extern void put_objfile_before (struct objfile *, struct objfile *);

extern void objfile_to_front (struct objfile *);

Index: gdb/symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.74.2.2
diff -u -r1.74.2.2 symfile.c
--- gdb/symfile.c 26 Nov 2002 03:14:15 -0000 1.74.2.2
+++ gdb/symfile.c 26 Nov 2002 03:42:31 -0000
@@ -38,6 +38,7 @@
#include "complaints.h"
#include "demangle.h"
#include "inferior.h" /* for write_pc */
+#include "filenames.h" /* for DOSish file names */
#include "gdb-stabs.h"
#include "gdb_obstack.h"
#include "completer.h"
@@ -104,6 +105,8 @@

static void add_shared_symbol_files_command (char *, int);

+static void reread_separate_symbols (struct objfile *objfile);
+
static void cashier_psymtab (struct partial_symtab *);

bfd *symfile_bfd_open (char *);
@@ -148,6 +151,8 @@

static void info_ext_lang_command (char *args, int from_tty);

+static char *find_separate_debug_file (struct objfile *objfile);
+
static void init_filename_language_table (void);

void _initialize_symfile (void);
@@ -887,7 +892,12 @@
{
struct objfile *objfile;
struct partial_symtab *psymtab;
+ char *debugfile;
bfd *abfd;
+ struct section_addr_info orig_addrs;
+
+ if (addrs)
+ orig_addrs = *addrs;

/* Open a bfd for the file, and give user a chance to burp if we'd be
interactively wiping out any existing symbols. */
@@ -962,6 +972,37 @@
}
}

+ debugfile = find_separate_debug_file (objfile);
+ if (debugfile)
+ {
+ if (from_tty || info_verbose)
+ {
+ printf_filtered ("loading separate debug info from '%s'",
+ debugfile);
+ wrap_here ("");
+ gdb_flush (gdb_stdout);
+ }
+
+ if (addrs != NULL)
+ {
+ objfile->separate_debug_objfile
+ = symbol_file_add (debugfile, from_tty, &orig_addrs, 0, flags);
+ }
+ else
+ {
+ objfile->separate_debug_objfile
+ = symbol_file_add (debugfile, from_tty, NULL, 0, flags);
+ }
+ objfile->separate_debug_objfile->separate_debug_objfile_backlink
+ = objfile;
+
+ /* Put the separate debug object before the normal one, this is so that
+ usage of the ALL_OBJFILES_SAFE macro will stay safe. */
+ put_objfile_before (objfile->separate_debug_objfile, objfile);
+
+ xfree (debugfile);
+ }
+
if (from_tty || info_verbose)
{
if (post_add_symbol_hook)
@@ -1057,6 +1098,135 @@
#endif
}

+static char *
+get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out)
+{
+ asection *sect;
+ bfd_size_type debuglink_size;
+ unsigned long crc32;
+ char *contents;
+ int crc_offset;
+ unsigned char *p;
+
+ sect = bfd_get_section_by_name (objfile->obfd, ".gnu_debuglink");
+
+ if (sect == NULL)
+ return NULL;
+
+ debuglink_size = bfd_section_size (objfile->obfd, sect);
+
+ contents = xmalloc (debuglink_size);
+ bfd_get_section_contents (objfile->obfd, sect, contents,
+ (file_ptr)0, (bfd_size_type)debuglink_size);
+
+ /* Crc value is stored after the filename, aligned up to 4 bytes. */
+ crc_offset = strlen (contents) + 1;
+ crc_offset = (crc_offset + 3) & ~3;
+
+ crc32 = bfd_get_32 (objfile->obfd, (bfd_byte *) (contents + crc_offset));
+
+ *crc32_out = crc32;
+ return contents;
+}
+
+static int
+separate_debug_file_exists (const char *name, unsigned long crc)
+{
+ unsigned long file_crc = 0;
+ int fd;
+ char buffer[8*1024];
+ int count;
+
+ fd = open (name, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ return 0;
+
+ while ((count = read (fd, buffer, sizeof (buffer))) > 0)
+ file_crc = calc_crc32 (file_crc, buffer, count);
+
+ close (fd);
+
+ return crc == file_crc;
+}
+
+static char *debug_file_directory = NULL;
+
+static char *
+find_separate_debug_file (struct objfile *objfile)
+{
+ asection *sect;
+ char *basename;
+ char *dir;
+ char *debugfile;
+ char *name_copy;
+ bfd_size_type debuglink_size;
+ unsigned long crc32;
+ int i;
+
+ basename = get_debug_link_info (objfile, &crc32);
+
+ if (basename == NULL)
+ return NULL;
+
+ dir = xstrdup (objfile->name);
+
+ /* Strip off filename part */
+ for (i = strlen(dir) - 1; i >= 0; i--)
+ {
+ if (IS_DIR_SEPARATOR (dir[i]))
+ break;
+ }
+ dir[i+1] = '\0';
+
+ debugfile = alloca (strlen (debug_file_directory) + 1
+ + strlen (dir)
+ + strlen (".debug/")
+ + strlen (basename)
+ + 1);
+
+ /* First try in the same directory as the original file: */
+ strcpy (debugfile, dir);
+ strcat (debugfile, basename);
+
+ if (separate_debug_file_exists (debugfile, crc32))
+ {
+ xfree (basename);
+ xfree (dir);
+ return xstrdup (debugfile);
+ }
+
+ /* Then try in a subdirectory called .debug */
+ strcpy (debugfile, dir);
+ strcat (debugfile, ".debug/");
+ strcat (debugfile, basename);
+
+ if (separate_debug_file_exists (debugfile, crc32))
+ {
+ xfree (basename);
+ xfree (dir);
+ return xstrdup (debugfile);
+ }
+
+ /* Then try in the global debugfile directory */
+ strcpy (debugfile, debug_file_directory);
+ strcat (debugfile, "/");
+ strcat (debugfile, dir);
+ strcat (debugfile, "/");
+ strcat (debugfile, basename);
+
+ if (separate_debug_file_exists (debugfile, crc32))
+ {
+ xfree (basename);
+ xfree (dir);
+ return xstrdup (debugfile);
+ }
+
+ xfree (basename);
+ xfree (dir);
+ return NULL;
+}
+
+
/* This is the symbol-file command. Read the file, analyze its
symbols, and add a struct symtab to a symtab list. The syntax of
the command is rather bizarre--(1) buildargv implements various
@@ -1902,6 +2072,8 @@
needs to keep track of (such as _sigtramp, or whatever). */

TARGET_SYMFILE_POSTREAD (objfile);
+
+ reread_separate_symbols (objfile);
}
}
}
@@ -1909,6 +2081,73 @@
if (reread_one)
clear_symtab_users ();
}
+
+
+/* Handle separate debug info for OBJFILE, which has just been
+ re-read:
+ - If we had separate debug info before, but now we don't, get rid
+ of the separated objfile.
+ - If we didn't have separated debug info before, but now we do,
+ read in the new separated debug info file.
+ - If the debug link points to a different file, toss the old one
+ and read the new one.
+ This function does *not* handle the case where objfile is still
+ using the same separate debug info file, but that file's timestamp
+ has changed. That case should be handled by the loop in
+ reread_symbols already. */
+static void
+reread_separate_symbols (struct objfile *objfile)
+{
+ char *debug_file;
+ unsigned long crc32;
+
+ /* Does the updated objfile's debug info live in a
+ separate file? */
+ debug_file = find_separate_debug_file (objfile);
+
+ if (objfile->separate_debug_objfile)
+ {
+ /* There are two cases where we need to get rid of
+ the old separated debug info objfile:
+ - if the new primary objfile doesn't have
+ separated debug info, or
+ - if the new primary objfile has separate debug
+ info, but it's under a different filename.
+
+ If the old and new objfiles both have separate
+ debug info, under the same filename, then we're
+ okay --- if the separated file's contents have
+ changed, we will have caught that when we
+ visited it in this function's outermost
+ loop. */
+ if (! debug_file
+ || strcmp (debug_file, objfile->separate_debug_objfile->name) != 0)
+ free_objfile (objfile->separate_debug_objfile);
+ }
+
+ /* If the new objfile has separate debug info, and we
+ haven't loaded it already, do so now. */
+ if (debug_file
+ && ! objfile->separate_debug_objfile)
+ {
+ /* Use the same section offset table as objfile itself.
+ Preserve the flags from objfile that make sense. */
+ objfile->separate_debug_objfile
+ = (symbol_file_add_with_addrs_or_offsets
+ (debug_file,
+ info_verbose, /* from_tty: Don't override the default. */
+ 0, /* No addr table. */
+ objfile->section_offsets, objfile->num_sections,
+ 0, /* Not mainline. See comments about this above. */
+ objfile->flags & (OBJF_MAPPED | OBJF_REORDERED
+ | OBJF_SHARED | OBJF_READNOW
+ | OBJF_USERLOADED)));
+ objfile->separate_debug_objfile->separate_debug_objfile_backlink
+ = objfile;
+ }
+}
+
+
\f

@@ -3417,4 +3656,18 @@
"cache.\n",
&setlist),
&showlist);
+
+ debug_file_directory = xstrdup (DEBUGDIR);
+ c = (add_set_cmd
+ ("debug-file-directory", class_support, var_string,
+ (char *) &debug_file_directory,
+ "Set the directory where separate debug symbols are searched for.\n"
+ "Separate debug symbols are first searched for in the same\n"
+ "directory as the binary, then in the .debug subdirectory,\n"
+ "and lastly at the path of the directory of the binary with\n"
+ "the global debug-file directory prepended\n",
+ &setlist));
+ add_show_from_set (c, &showlist);
+ set_cmd_completer (c, filename_completer);
+
}
Index: gdb/utils.c
===================================================================
RCS file: /cvs/src/src/gdb/utils.c,v
retrieving revision 1.85
diff -u -r1.85 utils.c
--- gdb/utils.c 12 Nov 2002 20:26:05 -0000 1.85
+++ gdb/utils.c 26 Nov 2002 03:42:34 -0000
@@ -2810,3 +2810,69 @@
xfree (real_path);
return result;
}
+
+unsigned long
+calc_crc32 (unsigned long crc, unsigned char *buf, size_t len)
+{
+ static const unsigned long crc32_table[256] =
+ {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d
+ };
+ unsigned char *end;
+
+ crc = ~crc & 0xffffffff;
+ for (end = buf + len; buf < end; ++buf)
+ crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
+ return ~crc & 0xffffffff;;
+}
Index: gdb/doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.131
diff -u -r1.131 gdb.texinfo
--- gdb/doc/gdb.texinfo 11 Oct 2002 16:13:15 -0000 1.131
+++ gdb/doc/gdb.texinfo 26 Nov 2002 03:42:46 -0000
@@ -10206,6 +10206,29 @@
Display the current autoloading size threshold, in megabytes.
@end table

+On @sc{elf} based systems, @value{GDBN} supports automatically loading
+symbol tables and debug information from a file separate from the
+executable. This works by putting information in the executable about
+the name and checksum of the file with debug information. When
+@value{GDBN} reads such an executable it automatically tries to locate
+the debug file and load it.
+
+@value{GDBN} searchs for the file first in the same directory as the
+executable, and then in a subdirectory called @file{.debug}.
+If both these fail @value{GDBN} looks in the global debug directory, with the
+full pathname of the executable. So if you are loading
+@file{/usr/bin/ls} and it references the debug file @file{ls.debug}
+@value{GDBN} will look for @file{usr/bin/ls.debug} in the global debug
+directory.
+
+@table @code
+@kindex set debug-file-directory
+@item set debug-file-directory @var{directory}
+Set the global directory where @value{GDBN} searches for separate
+debug files to @var{directory}.
+@end table
+
+
@node Symbol Errors
@section Errors reading symbol files