Implemented IMGLUE reloc + dumping
authorKim Knuttila <krk@cygnus>
Mon, 13 Nov 1995 12:54:05 +0000 (12:54 +0000)
committerKim Knuttila <krk@cygnus>
Mon, 13 Nov 1995 12:54:05 +0000 (12:54 +0000)
bfd/ChangeLog
bfd/coff-ppc.c

index 13d308c1b3f78afdb381deaac5ef2b383e5cc654..5b06e7d4d42f41d89bcb7c67e1e1155a519e4b08 100644 (file)
@@ -1,3 +1,18 @@
+Mon Nov 13 07:31:35 1995  Kim Knuttila  <krk@cygnus.com>
+
+       * coff-ppc.c (ppc_coff_link_hash_entry): added support for inline
+       glue for the relocs: IMGLUE and IFGLUE.
+       (record_toc): new function - tracks toc contents
+       (ppc_mark_symbol_as_glue): new function - supports the IMGLUE reloc
+       (coff_ppc_relocate_section): Added support and fixes for IMGLUE/IFGLUE
+       (ppc_coff_rtype2howto): removed invalid IMGLUE hack
+       (coff_ppc_rtype_to_howto): removed invalid IMGLUE hack
+
+       * peicode.h (coff_swap_scnhdr_out): Fixed invalid strcmp for ".reldata"
+       (pe_print_idata): New function - formats the idata section data
+       (pe_print_pdata): New function - formats the pdata section data
+       (pe_print_private_bfd_data): calls to above
+
 Sun Nov 12 12:23:24 1995  Stan Shebs  <shebs@andros.cygnus.com>
 
        * Makefile.in (bfd_libs_here, etc): Provide empty definitions.
index ae87505d67e68fec2a9749dd98668fa5ed8c0cdf..444f21173a46d9a7323ad6eff02a3500dd12d4f2 100644 (file)
@@ -26,6 +26,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* Current State:
    - objdump works
    - relocs generated by gas
+   - ld will link files, but they do not run.
+   - dlltool will not produce correct output in some .reloc cases, and will 
+     not produce the right glue code for dll function calls.
 */
 
 
@@ -47,6 +50,126 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "libcoff.h"
 
+/* In order not to add an int to every hash table item for every coff
+   linker, we define our own hash table, derived from the coff one */
+
+/* PE linker hash table entries. */
+
+struct ppc_coff_link_hash_entry
+{
+  struct coff_link_hash_entry root; /* First entry, as required  */
+
+  /* As we wonder around the relocs, we'll keep the assigned toc_offset
+     here */
+  bfd_vma toc_offset;               /* Our addition, as required */
+  int symbol_is_glue;
+  unsigned long int glue_insn;
+  char eye_catcher[8];
+};
+
+/* Need a 7 char string for an eye catcher */
+#define EYE "krkjunk"
+
+#define CHECK_EYE(addr) \
+ if (strcmp(addr, EYE) != 0) \
+  { \
+    fprintf(stderr,\
+    "File %s, line %d, Hash check failure, bad eye %8s\n", \
+    __FILE__, __LINE__, addr); \
+    abort(); \
+ }
+
+/* PE linker hash table.  */
+
+struct ppc_coff_link_hash_table
+{
+  struct coff_link_hash_table root; /* First entry, as required */
+};
+
+static struct bfd_hash_entry *ppc_coff_link_hash_newfunc
+  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+          const char *));
+
+/* Routine to create an entry in the link hash table.  */
+
+static struct bfd_hash_entry *
+ppc_coff_link_hash_newfunc (entry, table, string)
+     struct bfd_hash_entry *entry;
+     struct bfd_hash_table *table;
+     const char *string;
+{
+  struct ppc_coff_link_hash_entry *ret = 
+    (struct ppc_coff_link_hash_entry *) entry;
+
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (ret == (struct ppc_coff_link_hash_entry *) NULL)
+    ret = (struct ppc_coff_link_hash_entry *)
+      bfd_hash_allocate (table, 
+                        sizeof (struct ppc_coff_link_hash_entry));
+
+  if (ret == (struct ppc_coff_link_hash_entry *) NULL)
+    return NULL;
+
+  /* Call the allocation method of the superclass.  */
+  ret = ((struct ppc_coff_link_hash_entry *)
+        _bfd_coff_link_hash_newfunc ((struct bfd_hash_entry *) ret, 
+                                     table, string));
+
+  if (ret)
+    {
+      /* Initialize the local fields.  */
+      ret->toc_offset = 1;
+      ret->symbol_is_glue = 0;
+      ret->glue_insn = 0;
+      strcpy(ret->eye_catcher, EYE);
+    }
+
+  return (struct bfd_hash_entry *) ret;
+}
+
+/* Initialize a PE linker hash table.  */
+
+static boolean
+ppc_coff_link_hash_table_init (table, abfd, newfunc)
+     struct ppc_coff_link_hash_table *table;
+     bfd *abfd;
+     struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+                                               struct bfd_hash_table *,
+                                               const char *));
+{
+  return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc);
+}
+
+/* Create a PE linker hash table.  */
+
+static struct bfd_link_hash_table *
+ppc_coff_link_hash_table_create (abfd)
+     bfd *abfd;
+{
+  struct ppc_coff_link_hash_table *ret;
+
+  ret = ((struct ppc_coff_link_hash_table *)
+        bfd_alloc (abfd, sizeof (struct ppc_coff_link_hash_table)));
+  if (ret == NULL)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
+  if (! ppc_coff_link_hash_table_init (ret, abfd,
+                                       ppc_coff_link_hash_newfunc))
+    {
+      bfd_release (abfd, ret);
+      return (struct bfd_link_hash_table *) NULL;
+    }
+  return &ret->root.root;
+}
+
+/* Now, tailor coffcode.h to use our hash stuff */
+
+#define coff_bfd_link_hash_table_create ppc_coff_link_hash_table_create
+
+\f
 /* The nt loader points the toc register to &toc + 32768, in order to */
 /* use the complete range of a 16-bit displacement (I guess). We have */
 /* to adjust for this when we fix up loads displaced off the toc reg. */
@@ -581,6 +704,7 @@ static reloc_howto_type ppc_coff_howto_table[] =
 
 /* Some really cheezy macros that can be turned on to test stderr :-) */
 
+#define DEBUG_RELOC
 
 #ifdef DEBUG_RELOC
 #define UN_IMPL(x)                                           \
@@ -638,6 +762,43 @@ enum toc_type
   toc_64
 };
 
+struct list_ele
+{
+  struct list_ele *next;
+  bfd_vma addr;
+  int offset;
+  const char *name;
+};
+
+extern struct list_ele *head;
+extern struct list_ele *tail;
+
+static void
+record_toc(toc_section, our_toc_offset, name)
+     asection *toc_section;
+     int our_toc_offset;
+     const char *name;
+{
+  /* add this entry to our toc addr-offset-name list */
+  struct list_ele *t;
+  t = malloc(sizeof(struct list_ele));
+  t->next = 0;
+  t->offset = our_toc_offset;
+  t->name = name;
+  t->addr = toc_section->output_offset + our_toc_offset;
+
+  if (head == 0)
+    {
+      head = t;
+      tail = t;
+    }
+  else
+    {
+      tail->next = t;
+      tail = t;
+    }
+}
+
 /* record a toc offset against a symbol */
 static int
 ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
@@ -653,7 +814,7 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
   int element_size;
   int data;
   int offset;
-  struct coff_link_hash_entry *h;
+  struct ppc_coff_link_hash_entry *h;
   struct coff_symbol_struct *target;
   int ret_val;
   const char *name;
@@ -662,7 +823,11 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
 
   h = 0;
 
-  h = obj_coff_sym_hashes (abfd)[sym];
+  h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
+  if (h != 0)
+    {
+      CHECK_EYE(h->eye_catcher);
+    }
 
   if (h == 0) 
     { 
@@ -707,7 +872,7 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
     }
   else
     {
-      name = h->root.root.string;
+      name = h->root.root.root.string;
 
       /* check to see if there's a toc slot allocated. If not, do it
         here. It will be used in relocate_section */
@@ -736,6 +901,25 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
   return ret_val;
 }
 
+/* record a toc offset against a symbol */
+static void
+ppc_mark_symbol_as_glue(abfd, sym, rel)
+     bfd *abfd;
+     int sym;
+     struct internal_reloc *rel;
+{
+  struct ppc_coff_link_hash_entry *h;
+
+  h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
+
+  CHECK_EYE(h->eye_catcher);
+
+  h->symbol_is_glue = 1;
+  h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr);
+
+  return;
+}
+
 \f
 /* Provided the symbol, returns the value reffed */
 static long get_symbol_value PARAMS ((asymbol *));
@@ -882,7 +1066,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
   for (; rel < relend; rel++)
     {
       long symndx;
-      struct coff_link_hash_entry *h;
+      struct ppc_coff_link_hash_entry *h;
       struct internal_syment *sym;
       bfd_vma val;
 
@@ -895,20 +1079,20 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
       unsigned short junk    = EXTRACT_JUNK (rel->r_type);
   
 #ifdef DEBUG_RELOC
-  /* now examine flags */
-  if (r_flags != 0) 
-    {
-      fprintf (stderr, "Reloc with flags found!");
-      if ( r_flags & IMAGE_REL_PPC_NEG ) 
-       fprintf (stderr, " NEG");
-      if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
-       fprintf (stderr, " BRTAKEN");
-      if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
-       fprintf (stderr, " BRNTAKEN");
-      if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
-       fprintf (stderr, " TOCDEFN");
-      fprintf(stderr, "\n");
-    }
+      /* now examine flags */
+      if (r_flags != 0) 
+       {
+         fprintf (stderr, "Reloc with flags found!");
+         if ( r_flags & IMAGE_REL_PPC_NEG ) 
+           fprintf (stderr, " NEG");
+         if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+           fprintf (stderr, " BRTAKEN");
+         if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+           fprintf (stderr, " BRNTAKEN");
+         if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+           fprintf (stderr, " TOCDEFN");
+         fprintf(stderr, "\n");
+       }
 #endif
 
       symndx = rel->r_symndx;
@@ -924,7 +1108,13 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
        }
       else
        {
-         h = obj_coff_sym_hashes (input_bfd)[symndx];
+         h = (struct ppc_coff_link_hash_entry *) 
+           (obj_coff_sym_hashes (input_bfd)[symndx]);
+         if (h != 0) 
+           {
+             CHECK_EYE(h->eye_catcher);
+           }
+
          sym = syms + symndx;
        }
 
@@ -947,18 +1137,20 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
        }
       else
        {
-         if (h->root.type == bfd_link_hash_defined
-             || h->root.type == bfd_link_hash_defweak)
+         CHECK_EYE(h->eye_catcher);
+
+         if (h->root.root.type == bfd_link_hash_defined
+             || h->root.root.type == bfd_link_hash_defweak)
            {
-             sec = h->root.u.def.section;
-             val = (h->root.u.def.value
+             sec = h->root.root.u.def.section;
+             val = (h->root.root.u.def.value
                     + sec->output_section->vma
                     + sec->output_offset);
            }
          else
            {
              if (! ((*info->callbacks->undefined_symbol)
-                    (info, h->root.root.string, input_bfd, input_section,
+                    (info, h->root.root.root.string, input_bfd, input_section,
                      rel->r_vaddr - input_section->vma)))
                return false;
            }
@@ -1001,6 +1193,17 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
                  }
              }
 
+#if 0
+           if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+             {
+               /* Somehow, we are to assume that the toc has already been
+                  done for this one, and the offset is the value of
+                  the symbol? */
+               fprintf(stderr,
+                       "Symbol value %d\n", val);
+             }
+#endif
+
            /* 
             *  Amazing bit tricks present. As we may have seen earlier, we
             *  use the 1 bit to tell us whether or not a toc offset has been
@@ -1036,6 +1239,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
                else
                  {
                    /* write out the toc entry */
+                   record_toc(toc_section, our_toc_offset, strdup(name));
 #ifdef TOC_DEBUG
                    fprintf(stderr,
                            "Writing out toc_offset toc_section (%p,%p)+%d val %d for %s\n", 
@@ -1056,8 +1260,9 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
              }
            else
              {
-               const char *name = h->root.root.string;
+               const char *name = h->root.root.root.string;
                our_toc_offset = h->toc_offset;
+
                if ((our_toc_offset & 1) != 0)
                  {
                    /* if it has been written out, it is marked with the 
@@ -1072,6 +1277,8 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
                  }
                else
                  {
+                   record_toc(toc_section, our_toc_offset, strdup(name));
+
 #ifdef TOC_DEBUG
                    /* write out the toc entry */
                    fprintf(stderr,
@@ -1133,40 +1340,26 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
          }
          break;
        case IMAGE_REL_PPC_IFGLUE:
-         /* To solve this, we need to know whether or not the symbol */
-         /* appearing on the call instruction is a function included */
-         /* in the link or not. If it is, then we leave the nop instruction */
-         /* alone, and the reloc is done. */
-
-         /* Actually, for dll support on NT, this is likely not necessary at
-            all. For any library function, a glue code stub must be supplied
-            to the linker, and the glue will take care of the toc reload */
-         DUMP_RELOC2(howto->name, rel);
-#if 0
-         if (h == 0) 
-           {
-             /* this better be a static function */
-                 fprintf(stderr,
-                         "It's a static function.... \n");
-           }
-         else
-           {
-             /* this is an externally visible function */
-             /* is it present? */
-             if (h->root.type == bfd_link_hash_defined
-                 || h->root.type == bfd_link_hash_defweak)
-               {
-                 fprintf(stderr,
-                         "The function is present. \n");
-                 ;
-               }
-             else
-               {
-                 fprintf(stderr,
-                         "The function is not present. \n");
-               }
-           }
-#endif
+         {
+           /* To solve this, we need to know whether or not the symbol */
+           /* appearing on the call instruction is a glue function or not. */
+           /* A glue function must announce itself via a IMGLUE reloc, and */
+           /* the reloc contains the required toc restore instruction */
+         
+           bfd_vma x;
+           const char *my_name;
+           DUMP_RELOC2(howto->name, rel);
+
+           if (h != 0)
+             {
+               my_name = h->root.root.root.string;
+               if (h->symbol_is_glue == 1) 
+                 {
+                   x = bfd_get_32(input_bfd, loc);
+                   bfd_put_32(input_bfd, h->glue_insn, loc);
+                 }
+             }
+         }
          break;
        case IMAGE_REL_PPC_SECREL:
          /* Unimplemented: codeview debugging information */
@@ -1180,13 +1373,14 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
             symbol */
          break;
        case IMAGE_REL_PPC_ABSOLUTE:
-       case IMAGE_REL_PPC_IMGLUE:
          {
            const char *my_name;
            if (h == 0)
                my_name = (syms+symndx)->_n._n_name;
            else
-               my_name = h->root.root.string;
+             {
+               my_name = h->root.root.root.string;
+             }
 
            fprintf(stderr, 
                    "Warning: unsupported reloc %s <file %s, section %s>\n", 
@@ -1198,6 +1392,23 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
                    rel->r_symndx, my_name, rel->r_vaddr, rel->r_vaddr);  
          }
          break;
+       case IMAGE_REL_PPC_IMGLUE:
+         {
+           /* There is nothing to do now. This reloc was noted in the first
+              pass over the relocs, and the glue instruction extracted */
+           const char *my_name;
+           if (h->symbol_is_glue == 1) 
+             break;
+           my_name = h->root.root.root.string;
+           fprintf(stderr, 
+                   "Warning: previously missed IMGLUE reloc %s <file %s, section %s>\n", 
+                   howto->name,
+                   bfd_get_filename(input_bfd),
+                   input_section->name);
+           break;
+
+         }
+         break;
 
        case IMAGE_REL_PPC_ADDR32NB:
          {
@@ -1213,7 +1424,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
              {
                char *target = 0;
 
-               name = h->root.root.string;
+               name = h->root.root.root.string;
                if (strcmp(".idata$2", name) == 0)
                  target = "__idata2_magic__";
                else if (strcmp(".idata$4", name) == 0)
@@ -1234,15 +1445,18 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
                    abort();
                  }
 
-               val = myh->root.u.def.value + sec->output_section->vma + sec->output_offset;
+               val = myh->root.u.def.value + 
+                 sec->output_section->vma + sec->output_offset;
                if (first_thunk_address == 0)
                  {
                    int idata5offset;
                    myh = coff_link_hash_lookup (coff_hash_table (info),
                                                 "__idata5_magic__",
                                                 false, false, true);
-                   first_thunk_address = myh->root.u.def.value + sec->output_section->vma + 
-                     sec->output_offset - pe_data(output_bfd)->pe_opthdr.ImageBase;
+                   first_thunk_address = myh->root.u.def.value + 
+                     sec->output_section->vma + 
+                     sec->output_offset - 
+                       pe_data(output_bfd)->pe_opthdr.ImageBase;
 
                    idata5offset = myh->root.u.def.value;
                    myh = coff_link_hash_lookup (coff_hash_table (info),
@@ -1258,9 +1472,10 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
              }
 
            rstat = _bfd_relocate_contents (howto,
-                                           input_bfd, 
-                                           val - pe_data(output_bfd)->pe_opthdr.ImageBase,
-                                           loc);
+                             input_bfd, 
+                             val - 
+                             pe_data(output_bfd)->pe_opthdr.ImageBase,
+                             loc);
          }
          break;
 
@@ -1316,7 +1531,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
            if (symndx == -1)
              name = "*ABS*";
            else if (h != NULL)
-             name = h->root.root.string;
+             name = h->root.root.root.string;
            else if (sym == NULL)
              name = "*unknown*";
            else if (sym->_n._n_n._n_zeroes == 0
@@ -1360,6 +1575,26 @@ long int import_table_size;
 long int first_thunk_address;
 long int thunk_size;
 
+struct list_ele *head;
+struct list_ele *tail;
+
+void
+dump_toc(vfile)
+     void *vfile;
+{
+  FILE *file = vfile;
+  struct list_ele *t;
+
+  fprintf(file, 
+         " Offset Offset   Name if present\n");
+
+  for(t = head; t != 0; t=t->next)
+    {
+      fprintf(file,
+             " %2x  %04lx    %s\n",
+             t->offset - 32768, t->offset, t->name);
+    }
+}
 
 boolean
 ppc_allocate_toc_section (info) 
@@ -1455,20 +1690,20 @@ ppc_process_before_allocation (abfd, info)
        unsigned short junk    = EXTRACT_JUNK (rel->r_type);
 
 #ifdef DEBUG_RELOC
-  /* now examine flags */
-  if (r_flags != 0) 
-    {
-      fprintf (stderr, "Reloc with flags found!");
-      if ( r_flags & IMAGE_REL_PPC_NEG ) 
-       fprintf (stderr, " NEG");
-      if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
-       fprintf (stderr, " BRTAKEN");
-      if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
-       fprintf (stderr, " BRNTAKEN");
-      if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
-       fprintf (stderr, " TOCDEFN");
-      fprintf(stderr, "\n");
-    }
+       /* now examine flags */
+       if (r_flags != 0) 
+         {
+           fprintf (stderr, "Reloc with flags found!");
+           if ( r_flags & IMAGE_REL_PPC_NEG ) 
+             fprintf (stderr, " NEG");
+           if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+             fprintf (stderr, " BRTAKEN");
+           if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+             fprintf (stderr, " BRNTAKEN");
+           if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+               fprintf (stderr, " TOCDEFN");
+           fprintf(stderr, "\n");
+         }
 #endif
        
        DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
@@ -1479,6 +1714,9 @@ ppc_process_before_allocation (abfd, info)
            toc_offset = ppc_record_toc_entry(abfd, info, sec, 
                                              rel->r_symndx, default_toc);
            break;
+         case IMAGE_REL_PPC_IMGLUE:
+           ppc_mark_symbol_as_glue(abfd, rel->r_symndx, rel);
+           break;
          default:
            break;
          }
@@ -1779,8 +2017,6 @@ ppc_coff_rtype2howto (relent, internal)
       break;
     case IMAGE_REL_PPC_IMGLUE:
       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
-      /* IMGLUE relocs have big numbers in them. Don't know what for yet. */
-      internal->r_vaddr = 0; /* make it zero for now */
       break;
     default:
       fprintf(stderr, 
@@ -1876,8 +2112,6 @@ fprintf(stderr,
       break;
     case IMAGE_REL_PPC_IMGLUE:
       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
-      /* IMGLUE relocs have big numbers in them. Don't know what for yet. */
-      rel->r_vaddr = 0; /* make it zero for now */
       break;
     default:
       fprintf(stderr, 
@@ -2112,12 +2346,3 @@ TARGET_BIG_SYM =
 };
 
 #endif
-
-
-
-
-
-
-
-
-