From: wkd@asc.slb.com (W. K. Duttweiler)
Subject: GDB-4.7 bug fixes
Organization: GNUs Not Usenet
Distribution: gnu
Date: Tue, 5 Jan 1993 04:24:32 GMT

I have made some changes to GDB-4.7, configured for rs6000-ibm-aix, in
order to provide better support for mixed C/C++ programs using xlc/xlC
and for better support for shared libraries. I did not test these
changes on any other platform, but most are restricted to
xcoff-specific code anyway.

-wkd

William K. Duttweiler                   Schlumberger Austin Systems Center
(512) 331-3000                          PO Box 200015
wkd@asc.slb.com                         Austin, TX  78720-0015

Bugs fixed:

1) xlC generates odd stabs for enums, which caused GDB to crash. Its
stabs for CLASSES are completely different than G++, and these were
being ignored completely. A new routine was added to partially support
these stabs. xlC also uses different "trampoline code" to do
inter-module calls. The routine which recognizes such code was
modified to support this, so that 'step' works properly.

2) The .bi/.ei classes were not working properly because the begining
symbol value refers to the first line number entry, but NOT the
function entry which precedes the first line number. This caused ALL
inline functions from include files to start at line 1.

3) "const" and "volatile" qualifiers would create "disconnected"
types. Since the 'this' ptr in C++ member functions is "const", the
debugger was losing the actual struct being pointed at. This was
fixed.

4) The function vmap_symtab() in xcoffexec.c was reorganized to make
the remapping loop simpler. It also was fixed to get the remapping
offset right. The debugger was screwing up any exitsing breakpoints
when you loaded symbols for a new shared library.

5) Shared libraries can get remapped to different addresses every time
you run a program, so the symbols need to be remapped each time, not
just once. IBM's own DBX fails in this respect.

The following files were changed:

gdb-4.7/gdb/stabsread.c
gdb-4.7/gdb/xcoffread.c
gdb-4.7/gdb/rs6000-tdep.c
gdb-4.7/gdb/xcoffexec.c
gdb-4.7/gdb/tm-rs6000.h

Here are the diffs:

cedrick[wkd](63)% ls
rs6000-tdep.c	stabsread.c	tm-rs6000.h	xcoffexec.c	xcoffread.c
cedrick[wkd](64)% setenv SRC ~/gnu/gdb-4.7/gdb
cedrick[wkd](65)% foreach file (*)
? diff -btwc $file $SRC/$file
? end
*** rs6000-tdep.c	Mon Oct  5 19:41:50 1992
--- /home/ubt21/wkd/gnu/gdb-4.7/gdb/rs6000-tdep.c	Thu Dec 17 15:04:00 1992
***************
*** 882,887 ****
--- 882,888 ----
  CORE_ADDR pc;
  {
    register unsigned int ii, op;
+   int new_pc_ptr = read_register(11);   /* ptr to new PC if in tramp code */
  
    static unsigned trampoline_code[] = {
          0x800b0000,                     /*     l   r0,0x0(r11)  */
***************
*** 894,906 ****
          0
    };
  
    for (ii=0; trampoline_code[ii]; ++ii) {
      op  = read_memory_integer (pc + (ii*4), 4);
      if (op != trampoline_code [ii])
        return NULL;
    }
!   ii = read_register (11);              /* r11 holds destination addr   */
!   pc = read_memory_integer (ii, 4);     /* (r11) value                  */
    return pc;
  }
  
--- 895,944 ----
          0
    };
  
+   /*
+   ** xlC lays down its own inline trampoline code, instead of loading in
+   ** the glink.o stuff. It uses r12 instead of r11, and loads it from the
+   ** TOC ptr as the first instruction of the following code...
+   */
+   static unsigned xlC_tramp_code[] = {
+       0,                                /* dummy               */
+       0x90410014,                       /*      st r2,0x14(r1) */
+       0x800c0000,                       /*       l r0,0(r12)   */
+       0x804c0004,                       /*       l r2,4(r12)   */
+       0x7c0903a6,                       /*   mtctr r0          */
+       0x4e800420,                       /*    bctr             */
+       0
+   };
+ 
+   static unsigned load_r2_from_r12 = 0x81820000;
+ #define OFFSET_MASK (0xfff)
+   int offset = 0;
+       
    for (ii=0; trampoline_code[ii]; ++ii) {
      op  = read_memory_integer (pc + (ii*4), 4);
      if (op != trampoline_code [ii])
+     {
+         /*
+         ** Not the standard trampoline code... check if it is the C++
+         ** version... The first instruction is a "l r12,OFF(r2)". We need
+         ** to verify this AND get the offset.
+         */
+         op = read_memory_integer(pc, 4);
+         offset = op & OFFSET_MASK;      /* get offset */
+         op &= ~OFFSET_MASK;             /* clear offset */
+         if (op != load_r2_from_r12)
              return NULL;
+         for (ii=1; xlC_tramp_code[ii]; ++ii) {
+             op  = read_memory_integer (pc + (ii*4), 4);
+             if (op != xlC_tramp_code [ii])
+                 return NULL;
          }
!         ii = read_register(2);          /* get r2 */
!         new_pc_ptr = read_memory_integer(ii + offset, 4);
!         break;
!     }
!   }
!   pc = read_memory_integer (new_pc_ptr, 4); /* read value*/
    return pc;
  }
  
***************
*** 1101,1112 ****
  #define LOADINFOLEN     10
  
  /* FIXME Warning -- loadinfotextindex is used for a nefarious purpose by
!    tm-rs6000.h.  */
  
  static  struct loadinfo *loadinfo = NULL;
  static  int     loadinfolen = 0;
  static  int     loadinfotocindex = 0;
! int     loadinfotextindex = 0;
  
  
  void
--- 1139,1150 ----
  #define LOADINFOLEN     10
  
  /* FIXME Warning -- loadinfotextindex is used for a nefarious purpose by
!    tm-rs6000.h. [wkd] Fixed... */
  
  static  struct loadinfo *loadinfo = NULL;
  static  int     loadinfolen = 0;
  static  int     loadinfotocindex = 0;
! static  int     loadinfotextindex = 0;
  
  
  void
*** stabsread.c	Wed Oct  7 19:31:18 1992
--- /home/ubt21/wkd/gnu/gdb-4.7/gdb/stabsread.c	Tue Jan  5 09:00:44 1993
***************
*** 68,73 ****
--- 68,76 ----
  read_struct_type PARAMS ((char **, struct type *, struct objfile *));
  
  static struct type *
+ read_xlC_class_type PARAMS ((char **, struct type *, struct objfile *));
+ 
+ static struct type *
  read_array_type PARAMS ((char **, struct type *, struct objfile *));
  
  static struct type **
***************
*** 984,989 ****
--- 987,993 ----
            /* Set the type code according to the following letter.  */
            switch ((*pp)[0])
              {
+             case 'Y':                   /* RS6000 xlC class */
              case 's':
                code = TYPE_CODE_STRUCT;
                prefix = "struct ";
***************
*** 1130,1141 ****
  
      case 'k':                           /* Const qualifier on some type (Sun) */
        type = read_type (pp, objfile);
!       /* FIXME! For now, we ignore const and volatile qualifiers.  */
        break;
  
      case 'B':                           /* Volatile qual on some type (Sun) */
        type = read_type (pp, objfile);
!       /* FIXME! For now, we ignore const and volatile qualifiers.  */
        break;
  
  /* FIXME -- we should be doing smash_to_XXX types here.  */
--- 1134,1147 ----
  
      case 'k':                           /* Const qualifier on some type (Sun) */
        type = read_type (pp, objfile);
!       if (typenums[0] != -1)
!           *dbx_lookup_type(typenums) = type; /* point at referenced type */
        break;
  
      case 'B':                           /* Volatile qual on some type (Sun) */
        type = read_type (pp, objfile);
!       if (typenums[0] != -1)
!           *dbx_lookup_type(typenums) = type; /* point at referenced type */
        break;
  
  /* FIXME -- we should be doing smash_to_XXX types here.  */
***************
*** 1218,1223 ****
--- 1224,1237 ----
        type = read_struct_type (pp, type, objfile);
        break;
  
+     case 'Y':                           /* RS6000 xlC class type */
+       type = dbx_alloc_type (typenums, objfile);
+       if (!TYPE_NAME (type))
+         TYPE_NAME (type) = type_synonym_name;
+       type_synonym_name = 0;
+       type = read_xlC_class_type (pp, type, objfile);
+       break;
+ 
      case 'u':                           /* Union type */
        type = dbx_alloc_type (typenums, objfile);
        if (!TYPE_NAME (type))
***************
*** 1995,2000 ****
--- 2009,2319 ----
    return type;
  }
  
+ /*
+ ** Read the description of a class type as defined by the IBM xlC C++
+ ** compiler. For now, we *ONLY* honor the data members and baseclasses.
+ ** xlC uses 'u' for public, 'i' for private, and 'o' for protected, so we
+ ** can try to get the visibility right. The method types are
+ ** indecipherable to me at this time [wkd/12/11/92].
+ **
+ ** This code was cloned from read_struct_type and them modified.
+ */
+ 
+ static struct type *
+ read_xlC_class_type (pp, type, objfile)
+      char **pp;
+      register struct type *type;
+      struct objfile *objfile;
+ {
+   struct nextfield
+     {
+       struct nextfield *next;
+       int visibility;                   /* 0=public, 1=protected, 2=public */
+       struct field field;
+     };
+ 
+   struct next_fnfield
+     {
+       struct next_fnfield *next;
+       struct fn_field fn_field;
+     };
+ 
+   struct next_fnfieldlist
+     {
+       struct next_fnfieldlist *next;
+       struct fn_fieldlist fn_fieldlist;
+     };
+ 
+   register struct nextfield *list = 0;
+   struct nextfield *new;
+   register char *p;
+   int nfields = 0;
+   int non_public_fields = 0;
+   register int n;
+   int typenums[2];
+   int n_baseclasses = 0;
+ 
+   register struct next_fnfieldlist *mainlist = 0;
+   int nfn_fields = 0;
+ 
+   TYPE_CODE (type) = TYPE_CODE_STRUCT;
+   INIT_CPLUS_SPECIFIC(type);
+   TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
+ 
+   /* First comes the total size in bytes.  */
+ 
+   TYPE_LENGTH (type) = read_number (pp, 0);
+ 
+   /*
+   ** Following the size field, we always see 'c' or 's', which means
+   ** class or struct (I think). We can ignore this character, since all
+   ** the members of a struct get right public visibility modifier. Next,
+   ** an optional 'V', which means ... (I have no idea).
+   */
+   ++*pp;                                /* skip 'c' or 's' */
+   if (**pp == 'V')
+       ++*pp;                            /* skip this too */
+ 
+   /*
+   ** Next comes the list of baseclasses. This list is comma-separated
+   ** elements of the form u0:4 (<visibility><offset>:<type>). The list is
+   ** terminated by a '('. There is no leading count of the number of
+   ** baseclasses as in G++.
+   */
+   while (**pp != '(')
+   {
+       int offset;
+       struct type *baseclass;
+       int via_public;
+ 
+       if (**pp == '\\')
+           *pp = next_symbol_text ();
+ 
+       ALLOCATE_CPLUS_STRUCT_TYPE(type);
+ 
+       switch (**pp)
+       {
+       case 'i':
+       case 'o':
+           via_public = 0;
+           non_public_fields++;
+           break;
+       case 'u':
+           via_public = 2;
+           break;
+       default:
+           /* Bad visibility format.  */
+           return error_type (pp);
+       }
+       ++*pp;
+ 
+       /*
+       ** Offset of the portion of the object corresponding to this
+       ** baseclass.  Always zero in the absence of multiple inheritance.
+       */
+       offset = read_number (pp, ':');
+ 
+       /*
+       ** Don't call read_type to get the type from the type number
+       ** because the '(' terminator will puzzle it...
+       */
+       typenums[0] = 0;
+       typenums[1] = read_number(pp, 0);
+       baseclass = dbx_alloc_type(typenums, objfile);
+       n_baseclasses++;                  /* count it */
+       if (**pp == ',')
+           ++*pp;
+ 
+       /* Make this baseclass visible for structure-printing purposes.  */
+       new = (struct nextfield *) alloca (sizeof (struct nextfield));
+       memset (new, 0, sizeof (struct nextfield));
+       new->next = list;
+       list = new;
+       list->visibility = via_public;
+       list->field.type = baseclass;
+       list->field.name = type_name_no_tag (baseclass);
+       list->field.bitpos = offset;
+       list->field.bitsize = 0;  /* this should be an unpacked field! */
+       nfields++;
+   }
+   TYPE_N_BASECLASSES (type) = n_baseclasses;
+   {
+       int num_bytes = B_BYTES (n_baseclasses);
+       char *pointer;
+         
+       pointer = (char *) TYPE_ALLOC (type, num_bytes);
+       TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
+   }
+   B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), n_baseclasses);
+ 
+ 
+   /*
+   ** **pp == '(' at this point...
+   **
+   ** Now come the fields, as VIS:NAME:TYPE,BITPOS,BITSIZ; At the end, we
+   ** see a semicolon instead of a field. The VIS field can include a one
+   ** character modifier before the actual visibility character. 'c' means
+   ** constant. I'm gonna ignore them for now.
+   **
+   ** Oh,... a field can also be a friend class reference, which is
+   ** indicated by '(TYPE;' I'm gonna ignore these, too.
+   **
+   ** Also, the first field may be a vtable pointer, and it is always
+   ** something like 'cup9__....:__vfp:'. We will skip the stuff up to the
+   ** real identifier (the __vfp). (Cause I don't know what it all means).
+   **
+   ** xlC generates method fields by adding a '[' after the visibility
+   ** character, followed by an additional code before the first ':'. I
+   ** think the codes are 'c' for constructor, 'f' for function, and 'd'
+   ** for destructor. But, we are gonna ignore all methods anyway, and
+   ** simply scan to the ';' at the end of the field.
+   */
+ 
+   ++*pp;                                /* skip '(' */
+   while (**pp != ';')
+   {
+       /* Check for and handle cretinous dbx symbol name continuation!  */
+       if (**pp == '\\') *pp = next_symbol_text ();
+ 
+       p = *pp;
+       /*
+       ** Check for friend class field and skip to semicolon if so...
+       */
+       if (*p == '(')
+       {
+           while (*p != ';') p++;
+           *pp = p + 1;
+           continue;
+       }
+ 
+       /*
+       ** Get the visibility character... check the next character for '['
+       ** and simply skip to first semi-colon if it matches. 
+       **
+       ** Oh,... virtual functions have a vtable index following the
+       ** visibility character, preceding the '['. So, if the next
+       ** character is numeric, the field must be a function.
+       */
+       while ((*p != 'i') && (*p != 'o') && (*p != 'u')) p++;
+       if ((p[1] == '[') || ((p[1] >= '0') && (p[1] <= '9')))
+       {
+           while (*p != ';') p++;
+           *pp = p + 1;                  /* skip field terminator */
+           continue;                     /* back to enclosing while loop */
+       }
+ 
+       /*
+       ** Get space to record the next field's data.
+       */
+       new = (struct nextfield *) alloca (sizeof (struct nextfield));
+       memset (new, 0, sizeof (struct nextfield));
+       new->next = list;
+       list = new;
+ 
+       switch (*p++)
+       {
+       case 'i':
+           list->visibility = 0; /* private */
+           non_public_fields++;
+           break;
+           
+       case 'o':
+           list->visibility = 1; /* protected */
+           non_public_fields++;
+           break;
+           
+       case 'u':
+           list->visibility = 2; /* public */
+           break;
+       }
+ 
+       while (*p != ':') p++;            /* this will skip funky vtable */
+                                         /* goop */
+ 
+       p++;                              /* skip ':' */
+       *pp = p;                          /* remember Name ptr... */
+ 
+       while (*p != ':') p++;            /* find name terminator */
+       list->field.name =                /* copy name */
+           obsavestring (*pp, p - *pp,
+                         &objfile -> type_obstack);
+       *pp = p + 1;                      /* point at type now */
+       list->field.type = read_type (pp, objfile);
+       ++*pp;;                           /* Skip the comma.  */
+       list->field.bitpos = read_number (pp, ',');
+       list->field.bitsize = read_number (pp, ';');
+ 
+       {
+           /*
+           ** Detect an unpacked field and mark it as such.  dbx gives a
+           ** bit size for all fields.  Note that forward refs cannot be
+           ** packed, and treat enums as if they had the width of ints.
+           */
+           if (TYPE_CODE (list->field.type) != TYPE_CODE_INT
+               && TYPE_CODE (list->field.type) != TYPE_CODE_ENUM)
+               list->field.bitsize = 0;
+           if ((list->field.bitsize == 8 * TYPE_LENGTH (list->field.type)
+                || (TYPE_CODE (list->field.type) == TYPE_CODE_ENUM
+                    && (list->field.bitsize
+                        == 8 * TYPE_LENGTH (lookup_fundamental_type (objfile, FT_INTEGER)))
+                    )
+                )
+               &&
+               list->field.bitpos % 8 == 0)
+               list->field.bitsize = 0;
+           nfields++;
+       }
+   }
+ 
+   /* Now create the vector of fields, and record how big it is.
+      We need this info to record proper virtual function table information
+      for this class's virtual functions.  */
+ 
+   TYPE_NFIELDS (type) = nfields;
+   TYPE_FIELDS (type) = (struct field *)
+     TYPE_ALLOC (type, sizeof (struct field) * nfields);
+   memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+ 
+   if (non_public_fields)
+     {
+       ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ 
+       TYPE_FIELD_PRIVATE_BITS (type) = (B_TYPE *)
+         TYPE_ALLOC (type, B_BYTES (nfields));
+       B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
+ 
+       TYPE_FIELD_PROTECTED_BITS (type) = (B_TYPE *)
+         TYPE_ALLOC (type, B_BYTES (nfields));
+       B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
+     }
+ 
+   /* Copy the saved-up fields into the field vector.  */
+ 
+   for (n = nfields; list; list = list->next)
+     {
+       n -= 1;
+       TYPE_FIELD (type, n) = list->field;
+       if (list->visibility == 0)
+         SET_TYPE_FIELD_PRIVATE (type, n);
+       else if (list->visibility == 1)
+         SET_TYPE_FIELD_PROTECTED (type, n);
+     }
+ 
+   {
+     int i;
+     for (i = 0; i < TYPE_N_BASECLASSES (type); ++i)
+       {
+         if (TYPE_CODE (TYPE_BASECLASS (type, i)) == TYPE_CODE_UNDEF)
+           /* @@ Memory leak on objfile->type_obstack?  */
+           return error_type (pp);
+         TYPE_NFN_FIELDS_TOTAL (type) +=
+           TYPE_NFN_FIELDS_TOTAL (TYPE_BASECLASS (type, i));
+       }
+   }
+ 
+   return type;
+ }
+ 
  /* Read a definition of an array type,
     and create and return a suitable type object.
     Also creates a range type which represents the bounds of that
***************
*** 2120,2125 ****
--- 2439,2457 ----
        if (**pp == '\\') *pp = next_symbol_text ();
  
        p = *pp;
+ #if 1
+       /*
+       ** [wkd/12/10/92] the ibm xlC C++ compiler puts a -1: after the 'e'
+       ** for enums seen in C++ files. Skip the stupid -1: before skipping
+       ** to the next colon.
+       */
+       if ((p[0] == '-') && (p[1] == '1') && (p[2] == ':'))
+       {
+           p += 3;
+           *pp = p;                      /* dont let the -1: get into the */
+                                         /* first enum constant name string */
+       }
+ #endif
        while (*p != ':') p++;
        name = obsavestring (*pp, p - *pp, &objfile -> symbol_obstack);
        *pp = p + 1;
*** tm-rs6000.h	Fri Sep 18 03:09:18 1992
--- /home/ubt21/wkd/gnu/gdb-4.7/gdb/tm-rs6000.h	Tue Dec 15 12:33:27 1992
***************
*** 18,24 ****
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  
- extern int      symtab_relocated;
  
  /* Minimum possible text address in AIX */
  
--- 18,23 ----
***************
*** 29,35 ****
     if symbol table relocation wasn't done yet. */
  
  #define CORE_NEEDS_RELOCATION(PC)       \
!   if (!symtab_relocated && !inferior_pid && (PC) >  TEXT_SEGMENT_BASE)  \
      (PC) -= ( TEXT_SEGMENT_BASE + text_adjustment (exec_bfd));
  
  /* Load segment of a given pc value. */
--- 28,34 ----
     if symbol table relocation wasn't done yet. */
  
  #define CORE_NEEDS_RELOCATION(PC)       \
!   if (!inferior_pid && (PC) >  TEXT_SEGMENT_BASE)       \
      (PC) -= ( TEXT_SEGMENT_BASE + text_adjustment (exec_bfd));
  
  /* Load segment of a given pc value. */
***************
*** 119,126 ****
  /* When a child process is just starting, we sneak in and relocate
     the symbol table (and other stuff) after the dynamic linker has
     figured out where they go. But we want to do this relocation just
!    once. */
  
  extern int loadinfotextindex;
  
  #define SOLIB_CREATE_INFERIOR_HOOK(PID) \
--- 118,127 ----
  /* When a child process is just starting, we sneak in and relocate
     the symbol table (and other stuff) after the dynamic linker has
     figured out where they go. But we want to do this relocation just
!    once. [wkd] What a crock! We want to do this EVERY time, since they can
!    get remapped to different addresses */
  
+ #if 0
  extern int loadinfotextindex;
  
  #define SOLIB_CREATE_INFERIOR_HOOK(PID) \
***************
*** 128,133 ****
--- 129,138 ----
      if (loadinfotextindex == 0) \
          xcoff_relocate_symtab (PID);    \
    } while (0)
+ 
+ #else
+ #define SOLIB_CREATE_INFERIOR_HOOK(PID) xcoff_relocate_symtab(PID)
+ #endif
          
  
  /* Number of trap signals we need to skip over, once the inferior process
*** xcoffexec.c	Wed Oct  7 19:31:53 1992
--- /home/ubt21/wkd/gnu/gdb-4.7/gdb/xcoffexec.c	Tue Dec 15 13:29:47 1992
***************
*** 355,365 ****
  }
  
  
- /* true, if symbol table and minimal symbol table are relocated. */
- 
- int symtab_relocated = 0;
- 
- 
  /*  vmap_symtab -       handle symbol translation on vmapping */
  
  vmap_symtab(vp, old_start, vip)
--- 355,360 ----
***************
*** 371,404 ****
    register struct objfile *objfile;
    register struct minimal_symbol *msymbol;
    
    /*
!    * for each symbol table generated from the vp->bfd
     */
    ALL_OBJFILES (objfile)
      {
!       for (s = objfile -> symtabs; s != NULL; s = s -> next) {
!         
!         /* skip over if this is not relocatable and doesn't have a line table */
!         if (s->nonreloc && !LINETABLE (s))
            continue;
!         
!         /* matching the symbol table's BFD and the *vp's BFD is hairy.
!            exec_file creates a seperate BFD for possibly the
!            same file as symbol_file.FIXME ALL THIS MUST BE RECTIFIED. */
!         
!         if (objfile->obfd == vp->bfd) {
            /* if they match, we luck out. */
            ;
!         } else if (vp->member[0]) {
!           /* no match, and member present, not this one. */
            continue;
!         } else {
            struct stat si;
            FILE *io;
            
-           /*
-            * no match, and no member. need to be sure.
-            */
            io = bfd_cache_lookup(objfile->obfd);
            if (!io)
              fatal("cannot find BFD's iostream for sym");
--- 366,403 ----
    register struct objfile *objfile;
    register struct minimal_symbol *msymbol;
    
+   /* true, if symbol table and minimal symbol table are relocated. */
+ 
+   int symtab_relocated = 0;
+ 
+ 
    /*
!   ** for each symbol table generated from the vp->bfd
!   ** Matching the symbol table's BFD and the *vp's BFD is hairy.
!   ** exec_file creates a seperate BFD for possibly the
!   ** same file as symbol_file. 
!   **
!   ** We can ignore any objfile with no symbols. We can match any objfile
!   ** whose BFD is an exact match. We can match ones which refer to the
!   ** same file. Note that if 'vip' is NULL, then ONLY an exact BFD match
!   ** will work.
!   **
!   ** Match BFDs BEFORE looping on symtabs...
    */
    ALL_OBJFILES (objfile)
      {
!         if (!objfile->symtabs)
              continue;
!         else if (objfile->obfd == vp->bfd)
            /* if they match, we luck out. */
            ;
!         else if (!vip)
              continue;
!         else
!         {
            struct stat si;
            FILE *io;
            
            io = bfd_cache_lookup(objfile->obfd);
            if (!io)
              fatal("cannot find BFD's iostream for sym");
***************
*** 408,425 ****
            if (fstat(fileno(io), &si) < 0)
              fatal("cannot fstat BFD for sym");
            
!           if (vip && (si.st_dev != vip->st_dev
!               || si.st_ino != vip->st_ino))
              continue;
          }
          
          if (vp->tstart != old_start) {
! 
!           /* Once we find a relocation base address for one of the symtabs
!              in this objfile, it will be the same for all symtabs in this
!              objfile. Clean this algorithm. FIXME. */
! 
!           for (; s; s = s->next)
              if (!s->nonreloc || LINETABLE(s))
                  vmap_symtab_1(s, vp, old_start);
  
--- 407,423 ----
            if (fstat(fileno(io), &si) < 0)
              fatal("cannot fstat BFD for sym");
            
!           if (si.st_dev != vip->st_dev || si.st_ino != vip->st_ino)
              continue;
          }
          
+         /*
+         ** Got a match on BFD... process all the symbols that are
+         ** relocatable and have line tables...
+         */
          if (vp->tstart != old_start) {
!           symtab_relocated = 1;
!           for (s = objfile->symtabs; s; s = s->next)
              if (!s->nonreloc || LINETABLE(s))
                  vmap_symtab_1(s, vp, old_start);
  
***************
*** 433,439 ****
            ALL_MSYMBOLS (objfile, msymbol)
  #else
            for (msymbol = objfile->msymbols;
!                 msymbol->name || msymbol->address; (msymbol)++)
  #endif
                if (msymbol->address < TEXT_SEGMENT_BASE)
                  msymbol -> address += vp->tstart - old_start;
--- 431,437 ----
            ALL_MSYMBOLS (objfile, msymbol)
  #else
            for (msymbol = objfile->msymbols;
!                 msymbol && (msymbol->name || msymbol->address); (msymbol)++)
  #endif
                if (msymbol->address < TEXT_SEGMENT_BASE)
                  msymbol -> address += vp->tstart - old_start;
***************
*** 441,454 ****
             break;
          }
        }
-     }
  
!   if (vp->tstart != old_start) {
      /* breakpoints need to be relocated as well. */
!     fixup_breakpoints (0, TEXT_SEGMENT_BASE, vp->tstart - old_start);
    }
    
-   symtab_relocated = 1;
  }
  
  
--- 439,451 ----
             break;
          }
        }
  
!   if (symtab_relocated && vp->tstart != old_start) {
      /* breakpoints need to be relocated as well. */
!       fixup_breakpoints (old_start, vp->tend-vp->tstart+old_start,
!                          vp->tstart - old_start);
    }
    
  }
  
  
*** xcoffread.c	Fri Oct 16 14:16:59 1992
--- /home/ubt21/wkd/gnu/gdb-4.7/gdb/xcoffread.c	Tue Jan  5 08:49:21 1993
***************
*** 274,279 ****
--- 274,300 ----
  }
  
  
+ static void
+ exam_syms(
+     struct objfile *objfile)
+ {
+     register struct symtab *s;
+     static int flag = 0;
+     static char *debug = 0;
+ 
+     if (!flag)
+     {
+         debug = getenv("GDB_DEBUG");
+         flag = 1;
+     }
+     if (!debug || !objfile)
+         return;
+ 
+     for (s = objfile -> symtabs; s != NULL; s = s -> next)
+         if (s->filename)
+             printf("0x%x: '%s'\n", s, s->filename);
+ }
+ 
  /* add a given stab string into given stab vector. */
  
  static void
***************
*** 482,488 ****
    }
  
    inclTable [inclIndx].name  = cs->c_name;
!   inclTable [inclIndx].begin = cs->c_value;
  }
  
  
--- 503,520 ----
    }
  
    inclTable [inclIndx].name  = cs->c_name;
! 
!   /*
!   ** The xlC (IBM C++) compiler generates lots of .bi/.ei pairs for
!   ** "inline" functions. The cs->c_value entry is the offset to the first
!   ** line number entry in the line table. These entries are organized by
!   ** FUNCTION, so the first entry is always line 1 of a particular
!   ** function. The line entry which PRECEDES this value has a line number
!   ** flag of 0, and the symbol table index of the function. Hence, we
!   ** record the begin entry as the preceding line number entry so that
!   ** "process_linenos" will work properly.
!   */
!   inclTable [inclIndx].begin = cs->c_value - LINESZ;
  }
  
  
***************
*** 633,642 ****
  
  /*      start_subfile (inclTable[ii].name, (char*)0);  */
          start_subfile (" ?", (char*)0);
-         current_subfile->name = 
-                 obsavestring (inclTable[ii].name, strlen (inclTable[ii].name),
-                               &current_objfile->symbol_obstack);
  
          if (lv == lineTb) {
            current_subfile->line_vector = (struct linetable *)
                  xrealloc (lv, (sizeof (struct linetable)
--- 665,682 ----
  
  /*      start_subfile (inclTable[ii].name, (char*)0);  */
          start_subfile (" ?", (char*)0);
  
+         /*
+         ** current_subfile now refers to the one we just built with the
+         ** dummy name. Replace the name with the right name. We need to
+         ** free the duplicated name before replacing it. We must ALSO use
+         ** strdup() to allocate and copy the name into the subfile
+         ** pointer, just as start_subfile() does... we cannot allocate
+         ** this string on the obstack. [wkd/12/10/92]
+         */
+         free((PTR)current_subfile->name);
+         current_subfile->name = strdup(inclTable[ii].name);
+ 
          if (lv == lineTb) {
            current_subfile->line_vector = (struct linetable *)
                  xrealloc (lv, (sizeof (struct linetable)
***************
*** 2299,2304 ****
--- 2339,2346 ----
  
    /* Free debug section. */
    free_debugsection ();
+ 
+   exam_syms(objfile);
  
    /* Sort symbols alphabetically within each block.  */
    sort_syms ();
cedrick[wkd](66)% 

Newsgroups: gnu.gdb.bug