# 
# This patch adds XFree86 module support 
# to GDB's CVS snapshot of 2002-11-07.
# 
# Ported from original patch found somewhere 
# on the internet that was made for GDB 4.18.
# 
# Tested for i386 and x86-64 architectures 
# with XFree86 v4.x.x on SuSE Linux.
# 
# Michal Ludvig <michal@logix.cz> (c) 2002
# 
Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.92
diff -u -p -r1.92 breakpoint.c
--- breakpoint.c	24 Oct 2002 21:02:53 -0000	1.92
+++ breakpoint.c	7 Nov 2002 15:40:35 -0000
@@ -216,6 +216,8 @@ void _initialize_breakpoint (void);
 
 extern int addressprint;	/* Print machine addresses? */
 
+static int internal_breakpoint_number = -1;
+
 /* Are we executing breakpoint commands?  */
 static int executing_breakpoint_commands;
 
@@ -3036,6 +3038,7 @@ bpstat_what (bpstat bs)
 	  bs_class = bp_nostop;
 	  break;
 	case bp_shlib_event:
+	case bp_xfreemod_event:
 	  bs_class = shlib_event;
 	  break;
 	case bp_thread_event:
@@ -3223,7 +3226,8 @@ print_one_breakpoint (struct breakpoint 
     {bp_catch_vfork, "catch vfork"},
     {bp_catch_exec, "catch exec"},
     {bp_catch_catch, "catch catch"},
-    {bp_catch_throw, "catch throw"}
+    {bp_catch_throw, "catch throw"},
+    {bp_xfreemod_event, "XFree86 module events"}
   };
   
   static char *bpdisps[] =
@@ -3374,6 +3378,7 @@ print_one_breakpoint (struct breakpoint 
     case bp_shlib_event:
     case bp_thread_event:
     case bp_overlay_event:
+    case bp_xfreemod_event:
       if (addressprint)
 	{
 	  annotate_field (4);
@@ -3880,7 +3885,6 @@ make_breakpoint_permanent (struct breakp
 static struct breakpoint *
 create_internal_breakpoint (CORE_ADDR address, enum bptype type)
 {
-  static int internal_breakpoint_number = -1;
   struct symtab_and_line sal;
   struct breakpoint *b;
 
@@ -4029,6 +4033,32 @@ remove_thread_event_breakpoints (void)
       delete_breakpoint (b);
 }
 
+#ifdef XFREE_MODULE_SUPPORT
+void remove_xfreemod_event_breakpoints (void)
+{
+  register struct breakpoint *b, *temp;
+
+  ALL_BREAKPOINTS_SAFE (b, temp)
+    if (b->type == bp_xfreemod_event)
+      delete_breakpoint (b);
+}
+
+void create_xfreemod_event_breakpoint (CORE_ADDR address)
+{
+  struct breakpoint *b;
+  struct symtab_and_line sal;
+
+  init_sal (&sal);	/* initialize to zeroes */
+  sal.pc = address;
+  sal.section = find_pc_overlay (sal.pc);
+  b = set_raw_breakpoint (sal, bp_xfreemod_event);
+  b->number = internal_breakpoint_number--;
+  b->disposition = disp_donttouch;
+  b->type = bp_xfreemod_event;
+
+}
+#endif
+
 #ifdef SOLIB_ADD
 void
 remove_solib_event_breakpoints (void)
@@ -4506,6 +4536,7 @@ mention (struct breakpoint *b)
     case bp_shlib_event:
     case bp_thread_event:
     case bp_overlay_event:
+    case bp_xfreemod_event:
       break;
     }
   if (say_where)
Index: breakpoint.h
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.h,v
retrieving revision 1.13
diff -u -p -r1.13 breakpoint.h
--- breakpoint.h	16 Aug 2002 15:37:54 -0000	1.13
+++ breakpoint.h	7 Nov 2002 15:40:36 -0000
@@ -136,7 +136,12 @@ enum bptype
     /* These are catchpoints to implement "catch catch" and "catch throw"
        commands for C++ exception handling. */
     bp_catch_catch,
-    bp_catch_throw
+    bp_catch_throw,
+
+    /* As for bp_shlib_event but when the xfree module loader informs
+       us that a module has been loaded */
+    bp_xfreemod_event
+
 
 
   };
@@ -669,9 +674,13 @@ extern struct breakpoint *create_solib_e
 
 extern struct breakpoint *create_thread_event_breakpoint (CORE_ADDR);
 
+extern void create_xfreemod_event_breakpoint (CORE_ADDR);
+
 extern void remove_solib_event_breakpoints (void);
 
 extern void remove_thread_event_breakpoints (void);
+
+extern void remove_xfreemod_event_breakpoints (void);
 
 extern void disable_breakpoints_in_shlibs (int silent);
 
Index: dbxread.c
===================================================================
RCS file: /cvs/src/src/gdb/dbxread.c,v
retrieving revision 1.36
diff -u -p -r1.36 dbxread.c
--- dbxread.c	25 Oct 2002 22:25:55 -0000	1.36
+++ dbxread.c	7 Nov 2002 15:40:36 -0000
@@ -1210,7 +1210,7 @@ read_dbx_dynamic_symtab (struct objfile 
   do_cleanups (back_to);
 }
 
-#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+#if defined(SOFUN_ADDRESS_MAYBE_MISSING) || defined(XFREE_MODULE_SUPPORT)
 CORE_ADDR
 find_stab_function_addr (char *namestring, char *filename,
 			 struct objfile *objfile)
@@ -3144,7 +3144,7 @@ process_one_symbol (int type, int desc, 
 	    case 'F':
 	      function_stab_type = type;
 
-#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+#if defined(SOFUN_ADDRESS_MAYBE_MISSING) || defined(XFREE_MODULE_SUPPORT)
 	      /* Deal with the SunPRO 3.0 compiler which omits the address
 	         from N_FUN symbols.  */
 	      if (type == N_FUN
Index: dwarf2cfi.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2cfi.c,v
retrieving revision 1.20
diff -u -p -r1.20 dwarf2cfi.c
--- dwarf2cfi.c	2 Nov 2002 14:59:10 -0000	1.20
+++ dwarf2cfi.c	7 Nov 2002 15:40:36 -0000
@@ -1701,8 +1701,10 @@ cfi_write_fp (CORE_ADDR val)
 void
 cfi_pop_frame (struct frame_info *fi)
 {
-  char *regbuf = alloca (MAX_REGISTER_RAW_SIZE);
+  char regbuf[MAX_REGISTER_RAW_SIZE];
   int regnum;
+
+  fi = get_current_frame ();
 
   for (regnum = 0; regnum < NUM_REGS; regnum++)
     {
Index: elfread.c
===================================================================
RCS file: /cvs/src/src/gdb/elfread.c,v
retrieving revision 1.26
diff -u -p -r1.26 elfread.c
--- elfread.c	25 Oct 2002 22:25:55 -0000	1.26
+++ elfread.c	7 Nov 2002 15:40:36 -0000
@@ -265,7 +265,7 @@ elf_symtab_read (struct objfile *objfile
 	      symaddr = sym->value;
 	      if (symaddr == 0)
 		continue;
-	      symaddr += offset;
+	      symaddr += ANOFFSET (objfile->section_offsets, 0);
 	      msym = record_minimal_symbol_and_info
 		((char *) sym->name, symaddr,
 		 mst_solib_trampoline, NULL, sym->section, objfile);
@@ -307,10 +307,26 @@ elf_symtab_read (struct objfile *objfile
 	         interested in will have a section. */
 	      /* Bfd symbols are section relative. */
 	      symaddr = sym->value + sym->section->vma;
-	      /* Relocate all non-absolute symbols by the section offset.  */
-	      if (sym->section != &bfd_abs_section)
+	      /* Relocate all non-absolute symbols.  */
+	      if (STREQ (sym->section->name, ".text"))
 		{
-		  symaddr += offset;
+		  symaddr += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT(objfile));
+		}
+	      else if (STREQ (sym->section->name, ".data"))
+		{
+		  symaddr += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA(objfile));
+		}
+	      else if (STREQ (sym->section->name, ".bss"))
+		{
+		  symaddr += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS(objfile));
+		}
+	      else if (STREQ (sym->section->name, ".rodata"))
+		{
+		  symaddr += ANOFFSET (objfile->section_offsets, SECT_OFF_RODATA(objfile));
+		}
+	      else if (sym->section != &bfd_abs_section)
+		{
+		  symaddr += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT(objfile));
 		}
 	      /* For non-absolute symbols, use the type of the section
 	         they are relative to, to intuit text/data.  Bfd provides
@@ -344,7 +360,7 @@ elf_symtab_read (struct objfile *objfile
 		    {
 		      if (sym->name[0] == '.')
 			continue;
-		      symaddr += offset;
+		      symaddr += ANOFFSET (objfile->section_offsets, 0);
 		    }
 		}
 	      else if (sym->section->flags & SEC_CODE)
@@ -440,7 +456,7 @@ elf_symtab_read (struct objfile *objfile
 			  /* Relocate non-absolute symbols by the section offset. */
 			  if (sym->section != &bfd_abs_section)
 			    {
-			      symaddr += offset;
+			      symaddr += ANOFFSET (objfile->section_offsets, 0);
 			    }
 			  if (index != -1)
 			    sectinfo->sections[index] = symaddr;
Index: fork-child.c
===================================================================
RCS file: /cvs/src/src/gdb/fork-child.c,v
retrieving revision 1.17
diff -u -p -r1.17 fork-child.c
--- fork-child.c	7 Feb 2002 06:11:55 -0000	1.17
+++ fork-child.c	7 Nov 2002 15:40:36 -0000
@@ -377,6 +377,9 @@ fork_inferior (char *exec_file_arg, char
 #ifdef SOLIB_CREATE_INFERIOR_HOOK
   SOLIB_CREATE_INFERIOR_HOOK (pid);
 #endif
+#ifdef XFREE_MODULE_SUPPORT
+   xfreemod_create_inferior_hook(pid);
+#endif
 }
 
 /* An inferior Unix process CHILD_PID has been created by a call to
Index: gdb_indent.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdb_indent.sh,v
retrieving revision 1.4
diff -u -p -r1.4 gdb_indent.sh
--- gdb_indent.sh	24 Oct 2002 01:37:40 -0000	1.4
+++ gdb_indent.sh	7 Nov 2002 15:40:36 -0000
@@ -42,16 +42,6 @@ case `${indent} --version 2>/dev/null < 
     * ) echo "Indent is not GNU" 1>&2 ;;
 esac
 
-
-# Check that we're in the GDB source directory
-
-case `pwd` in
-    */gdb ) ;;
-    */sim/* ) ;;
-    * ) echo "Not in GDB directory" 1>&2 ; exit 1 ;;
-esac
-
-
 # Run indent per GDB specs
 
 types="\
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.74
diff -u -p -r1.74 infrun.c
--- infrun.c	24 Oct 2002 21:02:53 -0000	1.74
+++ infrun.c	7 Nov 2002 15:40:36 -0000
@@ -1482,12 +1482,16 @@ handle_inferior_event (struct execution_
 	  if (breakpoints_inserted)
 	    remove_breakpoints ();
 
-	  /* Check for any newly added shared libraries if we're
-	     supposed to be adding them automatically.  Switch
-	     terminal for any messages produced by
-	     breakpoint_re_set.  */
+	  /* Check for any newly added shared libraries or xfree
+	     modules if we're supposed to be adding them automatically. 
+	     Switch terminal for any messages produced
+	     by breakpoint_re_set.
+	   */
 	  target_terminal_ours_for_output ();
 	  SOLIB_ADD (NULL, 0, NULL, auto_solib_add);
+#ifdef XFREE_MODULE_SUPPORT
+	  xfreemod_add (NULL, 0, NULL);
+#endif
 	  target_terminal_inferior ();
 
 	  /* Reinsert breakpoints and continue.  */
@@ -2426,6 +2430,10 @@ process_event_stop_test:
 	     breakpoint_re_set.  */
 	  target_terminal_ours_for_output ();
 	  SOLIB_ADD (NULL, 0, NULL, auto_solib_add);
+#ifdef XFREE_MODULE_SUPPORT
+	  xfreemod_add (NULL, 0, NULL);
+#endif
+
 	  target_terminal_inferior ();
 
 	  /* Try to reenable shared library breakpoints, additional
Index: symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.71
diff -u -p -r1.71 symfile.c
--- symfile.c	17 Oct 2002 21:16:12 -0000	1.71
+++ symfile.c	7 Nov 2002 15:40:36 -0000
@@ -54,6 +54,8 @@
 #define O_BINARY 0
 #endif
 
+char oldname[100];
+
 #ifdef HPUXHPPA
 
 /* Some HP-UX related globals to clear when a new "main"
@@ -105,7 +107,7 @@ static void add_shared_symbol_files_comm
 
 static void cashier_psymtab (struct partial_symtab *);
 
-bfd *symfile_bfd_open (char *);
+/*bfd *symfile_bfd_open (char *);*/
 
 int get_section_index (struct objfile *, char *);
 
@@ -498,7 +500,7 @@ default_symfile_offsets (struct objfile 
       struct other_sections *osp ;
 
       osp = &addrs->other[i] ;
-      if (osp->addr == 0)
+      if (osp->addr == 0 || osp->sectindex < 0)
   	continue;
 
       /* Record all sections in offsets */
@@ -665,15 +667,16 @@ syms_from_objfile (struct objfile *objfi
        /* Calculate offsets for sections. */
       for (i=0 ; i < MAX_SECTIONS && addrs->other[i].name; i++)
 	{
+ 	  sect = bfd_get_section_by_name (objfile->obfd, addrs->other[i].name);
+	  /* This is the index used by BFD. */
+	  addrs->other[i].sectindex = sect ? sect->index : -1 ;
+
 	  if (addrs->other[i].addr != 0)
  	    {
- 	      sect = bfd_get_section_by_name (objfile->obfd, addrs->other[i].name);
  	      if (sect)
  		{
  		  addrs->other[i].addr -= bfd_section_vma (objfile->obfd, sect);
  		  lower_offset = addrs->other[i].addr;
-		  /* This is the index used by BFD. */
-		  addrs->other[i].sectindex = sect->index ;
  		}
  	      else
 		{
@@ -828,10 +831,70 @@ symbol_file_add (char *name, int from_tt
   struct partial_symtab *psymtab;
   bfd *abfd;
 
-  /* Open a bfd for the file, and give user a chance to burp if we'd be
-     interactively wiping out any existing symbols.  */
+#ifdef XFREE_MODULE_SUPPORT
+  struct cleanup *old_chain;
+  char *p;
+  /* Make a copy of the string that we can safely write into. */
+
+  name = strdup (name);
+  old_chain = make_cleanup(free, name);
+
+  p = strstr(name, ".a:");
+  if (p)
+  {
+      bfd *archive_bfd;
+      char *component_name = p + 3;
+      *(p+2) = 0;
+      archive_bfd = symfile_bfd_open (name, bfd_archive);
+
+      /* Look for the archive member that we want
+       *
+       * FIXME - we will be invoked several times for the same archive
+       * all this opening, closing and scanning is going to be dreadfully
+       * slow.
+       */
+      for (abfd = bfd_openr_next_archived_file (archive_bfd, NULL);
+	   abfd;
+	   abfd = bfd_openr_next_archived_file (archive_bfd, abfd))
+      {
+	  if (abfd->filename == NULL)
+	  {
+	      /* Some archive formats don't get the filenames filled in
+		 until the elements are opened.  */
+	      struct stat buf;
+	      bfd_stat_arch_elt (abfd, &buf);
+	  }
+	  /* printf_unfiltered("%s %s\n", abfd->filename, component_name); */
+	  if ((abfd->filename != NULL) &&
+	      (!strcmp (component_name, abfd->filename)))
+	  {
+	      break;
+	  }
+	  make_cleanup(bfd_close, abfd);
+	}
+      if (!bfd_check_format (abfd, bfd_object))
+      {
+	  /* FIXME: should be checking for errors from bfd_close (for one thing,
+	     on error it does not free all the storage associated with the
+	     bfd).  */
+	  bfd_close (archive_bfd);
+	  error ("\"%s\": can't read symbols: %s:%s.", name, component_name,
+		 bfd_errmsg (bfd_get_error ()));
+      }
+      /* The bfd filename points into the bfd's internal storage,
+	 not to a block obtained directly from malloc.
+	 Replace it with a copy so that free_objfile does not
+	 pass a bogus pointer to free */
+      bfd_get_filename (abfd) = strdup(bfd_get_filename (abfd));
+  }
+#endif
+  else
+  {
+      /* Open a bfd for the file, and give user a chance to burp if we'd be
+	 interactively wiping out any existing symbols.  */
 
-  abfd = symfile_bfd_open (name);
+      abfd = symfile_bfd_open (name, bfd_object);
+  }
 
   if ((have_full_symbols () || have_partial_symbols ())
       && mainline
@@ -870,9 +933,12 @@ symbol_file_add (char *name, int from_tt
 	    pre_add_symbol_hook (name);
 	  else
 	    {
-	      printf_filtered ("Reading symbols from %s...", name);
-	      wrap_here ("");
-	      gdb_flush (gdb_stdout);
+	      if(strcmp(name, oldname) != 0)
+	      {
+	        printf_filtered ("Reading symbols from %s...", name);
+	        wrap_here ("");
+	        gdb_flush (gdb_stdout);
+	      }
 	    }
 	}
       syms_from_objfile (objfile, addrs, mainline, from_tty);
@@ -906,11 +972,16 @@ symbol_file_add (char *name, int from_tt
 	post_add_symbol_hook ();
       else
 	{
-	  printf_filtered ("done.\n");
-	  gdb_flush (gdb_stdout);
+	  if(strcmp(name, oldname) != 0)
+	  {
+	    printf_filtered ("done.\n");
+	    gdb_flush (gdb_stdout);
+	  }
 	}
     }
 
+  snprintf(oldname, 99, "%s", name);
+
   if (objfile->sf == NULL)
     return objfile;	/* No symbols. */
 
@@ -919,6 +990,9 @@ symbol_file_add (char *name, int from_tt
   if (target_new_objfile_hook)
     target_new_objfile_hook (objfile);
 
+#ifdef XFREE_MODULE_SUPPORT
+  do_cleanups(old_chain);
+#endif
   return (objfile);
 }
 
@@ -1079,7 +1153,7 @@ set_initial_language (void)
    In case of trouble, error() is called.  */
 
 bfd *
-symfile_bfd_open (char *name)
+symfile_bfd_open (char *name, bfd_format format)
 {
   bfd *sym_bfd;
   int desc;
@@ -1119,7 +1193,7 @@ symfile_bfd_open (char *name)
     }
   sym_bfd->cacheable = 1;
 
-  if (!bfd_check_format (sym_bfd, bfd_object))
+  if (!bfd_check_format (sym_bfd, format))
     {
       /* FIXME: should be checking for errors from bfd_close (for one thing,
          on error it does not free all the storage associated with the
Index: symfile.h
===================================================================
RCS file: /cvs/src/src/gdb/symfile.h,v
retrieving revision 1.14
diff -u -p -r1.14 symfile.h
--- symfile.h	17 Oct 2002 21:16:12 -0000	1.14
+++ symfile.h	7 Nov 2002 15:40:36 -0000
@@ -254,7 +254,7 @@ extern void discard_psymtab (struct part
 
 extern void find_lowest_section (bfd *, asection *, PTR);
 
-extern bfd *symfile_bfd_open (char *);
+extern bfd *symfile_bfd_open (char *, bfd_format);
 
 extern int get_section_index (struct objfile *, char *);
 
Index: xfreemod.c
===================================================================
RCS file: xfreemod.c
diff -N xfreemod.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ xfreemod.c	7 Nov 2002 15:40:36 -0000
@@ -0,0 +1,306 @@
+/* Handle XFree dynamically loaded modules
+   
+This file is not an official part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcore.h"
+#include "gdb-stabs.h"
+#include "target.h"
+#include "breakpoint.h"
+#include "language.h"
+#include "command.h"
+#include "gdb_regex.h"
+
+/* The XFree server has its own dynamic load mechanism. Unlike shared
+ * libraries it loads regular .o (or even .a) files. GDB support for
+ * tracking loaded modules is very similar to shared libraries however
+ * (in fact much of this code originated in solib.c).
+ *
+ * There are a few differences. We don't need to do very much in the
+ * create_inferior hook as no modules are loaded at that point so we
+ * just tidy up after the last run, tell the inferior that we're
+ * around and insert a breakpoint so we get chance to do something
+ * when a module is loaded.
+ *
+ */
+
+static char *xfreemod_break_names[] = {
+  "_loader_debug_state",
+  NULL
+};
+
+#define MOD_LIST "ModList"
+
+static struct mod_list *mod_list_head;	/* List of known modules */
+
+/* Called when the inferior starts, just after the shared library hook */
+void
+xfreemod_create_inferior_hook (void)
+{
+  struct mod_list *mod;
+  struct mod_list *next_mod;
+  struct minimal_symbol *msymbol;
+  char **bkpt_namep;
+
+  /* First, remove any existing breakpoints.  Their addresses
+     may have changed since the last time we ran the program.  */
+  remove_xfreemod_event_breakpoints ();
+
+  /* And our copy of the inferior's modules */
+  for (mod = mod_list_head; mod; mod = next_mod)
+    {
+      next_mod = mod->next;
+      free (mod);
+    }
+  mod_list_head = 0;
+
+  msymbol = lookup_minimal_symbol ("DebuggerPresent", NULL, symfile_objfile);
+  if (msymbol)
+    {
+      char flag = 1;
+
+      int status = target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
+					&flag,
+					sizeof (flag));
+    }
+
+  /* Scan through the list of symbols, trying to look up the symbol and
+     set a breakpoint there. */
+  for (bkpt_namep = xfreemod_break_names; *bkpt_namep != NULL; bkpt_namep++)
+    {
+      msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
+      if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+	{
+	  create_xfreemod_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
+	}
+    }
+}
+
+/* Common symbols are not given addresses until the final link - which
+ * in this case is when the module is loaded so we need to read the
+ * addresses for these symbols from the inferior.
+ */
+void
+add_common_symbols (struct mod_list *mod)
+{
+  LDRCommonPtr commons;
+  int i;
+  int status;
+
+  if (mod->commonslen)
+    {
+      init_minimal_symbol_collection ();
+      make_cleanup_discard_minimal_symbols ();
+
+      commons = xmalloc (mod->commonslen * sizeof (LDRCommon));
+
+      status = target_read_memory (mod->commons,
+				   (char *) commons,
+				   mod->commonslen * sizeof (LDRCommon));
+      for (i = 0; i < mod->commonslen; i++)
+	{
+	  char *name = xmalloc (commons[i].namelen + 1);
+	  status = target_read_memory ((CORE_ADDR) commons[i].name,
+				       name, commons[i].namelen + 1);
+	  prim_record_minimal_symbol (name, (CORE_ADDR) commons[i].addr,
+				      mst_bss, mod->objfile);
+	  free (name);
+	}
+      install_minimal_symbols (mod->objfile);
+      free (commons);
+    }
+}
+
+
+/* Read the list of loaded modules from the inferior and add any new
+ * ones to our local copy
+ */
+void
+add_modules (int from_tty)
+{
+  struct minimal_symbol *msymbol;
+  CORE_ADDR modrec_addr = 0;
+  LDRModuleRec ldr_rec;
+  char *mod_name;
+  struct mod_list *mod;
+
+  msymbol = lookup_minimal_symbol (MOD_LIST, NULL, symfile_objfile);
+  if (msymbol)
+    {
+      int status = target_read_memory (SYMBOL_VALUE_ADDRESS (msymbol),
+				       (char *) &modrec_addr,
+				       sizeof (CORE_ADDR));
+      while (modrec_addr != 0)
+	{
+	  status = target_read_memory (modrec_addr,
+				       (char *) &ldr_rec,
+				       sizeof (LDRModuleRec));
+	  mod_name = xmalloc (ldr_rec.namelen + 1);
+	  status = target_read_memory ((CORE_ADDR) ldr_rec.name,
+				       mod_name, ldr_rec.namelen + 1);
+
+	  for (mod = mod_list_head; mod; mod = mod->next)
+	    {
+	      if (strcmp (mod_name, mod->mod_name) == 0)
+		break;
+	    }
+	  if (!mod)
+	    {
+	      mod = xmalloc (sizeof (struct mod_list));
+	      mod->mod_name = mod_name;
+	      mod->symbols_loaded = 0;
+	      mod->objfile = 0;
+	      mod->from_tty = from_tty;
+	      mod->text_addr = (CORE_ADDR) ldr_rec.text;
+	      mod->data_addr = (CORE_ADDR) ldr_rec.data;
+	      mod->rodata_addr = (CORE_ADDR) ldr_rec.rodata;
+	      mod->bss_addr = (CORE_ADDR) ldr_rec.bss;
+	      mod->commons = (CORE_ADDR) ldr_rec.commons;
+	      mod->commonslen = ldr_rec.commonslen;
+	      mod->next = mod_list_head;
+	      mod_list_head = mod;
+
+	    }
+	  else
+	    free (mod_name);
+	  modrec_addr = (CORE_ADDR) ldr_rec.next;
+	}
+    }
+}
+
+/* A small stub to get us past the arg-passing pinhole of catch_errors.  */
+static int
+module_add_stub (char *arg)
+{
+  struct mod_list *mod = (struct mod_list *) arg;
+  struct section_addr_info text_addr;
+
+  memset (&text_addr, '\0', sizeof (text_addr));
+  text_addr.other[0].name = ".text";
+  text_addr.other[0].addr = mod->text_addr;
+  text_addr.other[1].name = ".data";
+  text_addr.other[1].addr = mod->data_addr;
+  text_addr.other[2].name = ".rodata";
+  text_addr.other[2].addr = mod->rodata_addr;
+  text_addr.other[3].name = ".bss";
+  text_addr.other[3].addr = mod->bss_addr;
+
+  mod->objfile = symbol_file_add (mod->mod_name, mod->from_tty,
+				  &text_addr, 0, OBJF_SHARED);
+  return (1);
+}
+
+void
+xfreemod_add (arg_string, from_tty, target)
+     char *arg_string;
+     int from_tty;
+     struct target_ops *target;
+{
+  struct mod_list *mod;
+  char *re_err;
+
+  if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
+    error ("Invalid regexp: %s", re_err);
+
+  add_modules (from_tty);
+  for (mod = mod_list_head; mod; mod = mod->next)
+    if (mod->mod_name[0] && re_exec (mod->mod_name))
+      {
+	mod->from_tty = from_tty;
+	if (mod->symbols_loaded)
+	  {
+	    if (from_tty)
+	      printf_unfiltered ("Symbols already loaded for %s\n",
+				 mod->mod_name);
+	  }
+	else
+	  {
+	    mod->being_read = 1;
+	    if ((mod->symbols_loaded =
+		 catch_errors ((catch_errors_ftype *) module_add_stub,
+			       (char *) mod,
+			       "Error while reading server module symbols:\n",
+			       RETURN_MASK_ALL)))
+	      add_common_symbols (mod);
+	    mod->being_read = 0;
+	  }
+      }
+}
+
+/* Request reading of module's symbols */
+static void
+module_command (char *args, int from_tty)
+{
+  dont_repeat ();
+  xfreemod_add (args, from_tty, (struct target_ops *) 0);
+}
+
+/* List currently known modules and the status of each */
+static void
+info_modules_command (char *ignore, int from_tty)
+{
+  struct mod_list *mod;
+  int header_done = 0;
+  int addr_width;
+  char *addr_fmt;
+
+  if (exec_bfd == NULL)
+    {
+      printf_unfiltered ("No exec file.\n");
+      return;
+    }
+
+#ifndef TARGET_ELF64
+  addr_width = 8 + 4;
+  addr_fmt = "08l";
+#else
+  addr_width = 16 + 4;
+  addr_fmt = "016l";
+#endif
+
+  for (mod = mod_list_head; mod; mod = mod->next)
+    {
+      if (!header_done)
+	{
+	  printf_unfiltered ("%-*s%-*s%-12s%s\n", addr_width, "Text",
+			     addr_width, "Data", "Syms Read", "Module File");
+	  header_done++;
+	}
+      printf_unfiltered ("%-*s", addr_width,
+			 local_hex_string_custom (mod->text_addr, addr_fmt));
+      printf_unfiltered ("%-*s", addr_width,
+			 local_hex_string_custom (mod->data_addr, addr_fmt));
+      printf_unfiltered ("%-12s", mod->symbols_loaded ? "Yes" : "No");
+      printf_unfiltered ("%s\n", mod->mod_name);
+    }
+  if (mod_list_head == NULL)
+    printf_unfiltered ("No modules loaded at this time.\n");
+}
+
+void
+_initialize_xfreemod (void)
+{
+  add_com ("module", class_files, module_command,
+	   "Load shared object library symbols for files matching REGEXP.");
+  add_info ("modules", info_modules_command,
+	    "Status of loaded shared object libraries.");
+}
Index: xfreemod.h
===================================================================
RCS file: xfreemod.h
diff -N xfreemod.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ xfreemod.h	7 Nov 2002 15:40:36 -0000
@@ -0,0 +1,69 @@
+/* Handle XFree dynamically loaded modules
+   
+This file is not an official part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <sys/types.h>
+
+#ifndef SOLIB_ADD
+#error  XFree module support requires shared library support
+#endif
+
+#define XFREE_MODULE_SUPPORT
+
+#ifdef __STDC__		/* Forward decl's for prototypes */
+struct target_ops;
+#endif
+
+/* XFree loader Interface to GDB */
+typedef	struct {
+	unsigned char *name;       /* Name of this symbol */
+	unsigned int  namelen;     /* Name of this module */
+	void          *addr;	   /* Start address of the .text section */
+} LDRCommon, *LDRCommonPtr;
+
+typedef	struct {
+	unsigned int  version;     /* Version of this struct */
+	unsigned char *name;       /* Name of this module */
+	unsigned int  namelen;     /* Length of name */
+	void          *text;	   /* Start address of the .text section */
+	void          *data;	   /* Start address of the .data section */
+	void          *rodata;	   /* Start address of the .rodata section */
+	void          *bss;	   /* Start address of the .bss section */
+        LDRCommonPtr  commons;     /* List of commmon symbols */
+        int           commonslen;  /* Number of common symbols */
+	struct LDRModuleRec *next; /* Next module record in chain */
+} LDRModuleRec, *LDRModulePtr;
+
+/* Local copy of above */
+struct mod_list {
+    struct mod_list *next;	/* next structure in linked list */
+    char *mod_name;		/* module name */
+    char symbols_loaded;	/* flag: symbols read in yet? */
+    char from_tty;		/* flag: print msgs? */
+    struct objfile *objfile;	/* objfile for loaded module */
+    CORE_ADDR text_addr;	/* Address at which text was loaded */
+    CORE_ADDR data_addr;	/* Address at which data was loaded */
+    CORE_ADDR rodata_addr;	/* Address at which read-only data was loaded */
+    CORE_ADDR bss_addr;		/* Address at which bss was loaded */
+    CORE_ADDR commons;		/* List of commmon symbols */
+    int commonslen;		/* Number of common symbols */
+    int being_read;             /* Somewhat hacky, used to identify module for offsets */
+};
+
+extern void xfreemod_create_inferior_hook();
+extern void xfreemod_add PARAMS ((char *, int, struct target_ops *));
+
Index: config/nm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/nm-linux.h,v
retrieving revision 1.12
diff -u -p -r1.12 nm-linux.h
--- config/nm-linux.h	24 Feb 2002 22:56:04 -0000	1.12
+++ config/nm-linux.h	7 Nov 2002 15:40:36 -0000
@@ -41,6 +41,7 @@
 #ifdef HAVE_LINK_H
 #define SVR4_SHARED_LIBS
 #include "solib.h"             /* Support for shared libraries.  */
+#include "xfreemod.h"          /* Support for XFree86 modules.   */
 #endif
 
 
Index: config/i386/linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/linux.mh,v
retrieving revision 1.12
diff -u -p -r1.12 linux.mh
--- config/i386/linux.mh	11 May 2002 17:22:27 -0000	1.12
+++ config/i386/linux.mh	7 Nov 2002 15:40:37 -0000
@@ -4,7 +4,7 @@ XM_FILE= xm-i386.h
 
 NAT_FILE= nm-linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o linux-proc.o \
-	core-aout.o i386-nat.o i386-linux-nat.o \
+	core-aout.o i386-nat.o i386-linux-nat.o xfreemod.o \
 	proc-service.o thread-db.o lin-lwp.o linux-proc.o gcore.o
 
 # The dynamically loaded libthread_db needs access to symbols in the
Index: config/i386/x86-64linux.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/x86-64linux.mh,v
retrieving revision 1.7
diff -u -p -r1.7 x86-64linux.mh
--- config/i386/x86-64linux.mh	1 Jul 2002 22:09:52 -0000	1.7
+++ config/i386/x86-64linux.mh	7 Nov 2002 15:40:37 -0000
@@ -6,6 +6,6 @@ NAT_FILE= nm-x86-64linux.h
 NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
 	core-aout.o i386-nat.o x86-64-linux-nat.o \
 	proc-service.o thread-db.o lin-lwp.o \
-	linux-proc.o gcore.o 
+	linux-proc.o gcore.o xfreemod.o
 
 LOADLIBES = -ldl -rdynamic
