PowerPC DLL Support
authorKim Knuttila <krk@cygnus>
Fri, 1 Dec 1995 01:01:42 +0000 (01:01 +0000)
committerKim Knuttila <krk@cygnus>
Fri, 1 Dec 1995 01:01:42 +0000 (01:01 +0000)
bfd/ChangeLog
bfd/coff-ppc.c
bfd/coffcode.h

index 5986cb96a8b2887a9fc16b9946b1c9acc24d1896..60624ef12c85833eb09bc8573018b073caf836db 100644 (file)
@@ -1,3 +1,17 @@
+Thu Nov 30 19:32:26 1995  Kim Knuttila  <krk@cygnus.com>
+
+       * coff-ppc.c: Added macros to tidy up toc cell treatment. Numerous
+       uses as well. Added a new howto to deal with TOCREL16 relocs that 
+       are TOCDEFN as well.
+       (coff_ppc_relocate_section): Expanded treatment of ADDR32NB relocs
+       to handle RVA relocs from dlltool.
+       (ppc_coff_rtype2howto): TOCDEFN reloc addition.
+       (coff_ppc_rtype_to_howto): TOCDEFN reloc addition.
+       (ppc_coff_reloc_type_lookup): TOCDEFN reloc addition.
+
+       * coffcode.h (coff_set_alignment_hook): check idata$X sections 
+       to get the right section alignment.
+
 Thu Nov 30 16:48:18 1995  Ian Lance Taylor  <ian@cygnus.com>
 
        * elf.c (_bfd_elf_make_section_from_shdr): Don't set lma based on
index 25deb99e6d7ef86c5e1056e546858358552d99ba..379ef4e3406badfb0449238131016688c7ca95fb 100644 (file)
@@ -50,6 +50,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "libcoff.h"
 
+/* The toc is a set of bfd_vma fields. We use the fact that valid         */
+/* addresses are even (i.e. the bit representing "1" is off) to allow     */
+/* us to encode a little extra information in the field                   */
+/* - Unallocated addresses are intialized to 1.                           */
+/* - Allocated addresses are even numbers.                                */
+/* The first time we actually write a reference to the toc in the bfd,    */
+/* we want to record that fact in a fixup file (if it is asked for), so   */
+/* we keep track of whether or not an address has been written by marking */
+/* the low order bit with a "1" upon writing                              */
+
+#define SET_UNALLOCATED(x)  ((x) = 1)
+#define IS_UNALLOCATED(x)   ((x) == 1)
+
+#define IS_WRITTEN(x)       ((x) & 1)
+#define MARK_AS_WRITTEN(x)  ((x) |= 1)
+#define MAKE_ADDR_AGAIN(x)  ((x) &= ~1)
+
 /* 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 */
 
@@ -119,7 +136,7 @@ ppc_coff_link_hash_newfunc (entry, table, string)
   if (ret)
     {
       /* Initialize the local fields.  */
-      ret->toc_offset = 1;
+      SET_UNALLOCATED(ret->toc_offset);
       ret->symbol_is_glue = 0;
       ret->glue_insn = 0;
       strcpy(ret->eye_catcher, EYE);
@@ -238,6 +255,8 @@ ppc_coff_link_hash_table_create (abfd)
 #define IMAGE_REL_PPC_REFLO             0x0011
 #define IMAGE_REL_PPC_PAIR              0x0012
 
+/* This is essentially the same as tocrel16, with TOCDEFN assumed */
+#define IMAGE_REL_PPC_TOCREL16_DEFN     0x0013
 
 /*  Flag bits in IMAGE_RELOCATION.TYPE */
 
@@ -693,7 +712,25 @@ static reloc_howto_type ppc_coff_howto_table[] =
         true,                  /* partial_inplace */                      
         0xffffffff,            /* src_mask */                             
         0xffffffff,            /* dst_mask */                             
-        false)                 /* pcrel_offset */
+        false),                /* pcrel_offset */
+
+  /* IMAGE_REL_PPC_TOCREL16_DEFN 0x0013 */
+  /*   16-bit offset from TOC base, without causing a definition */
+  /* Used: */
+  HOWTO ( (IMAGE_REL_PPC_TOCREL16 | IMAGE_REL_PPC_TOCDEFN), /* type */ 
+        0,                     /* rightshift */                           
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */ 
+        16,                    /* bitsize */                   
+        false,                 /* pc_relative */                          
+        0,                     /* bitpos */                               
+        complain_overflow_dont, /* complain_on_overflow */
+        0,                     /* special_function */                     
+        "TOCREL16, TOCDEFN",   /* name */
+        false,                 /* partial_inplace */                      
+        0xffff,                /* src_mask */                             
+        0xffff,                /* dst_mask */                             
+        false),                /* pcrel_offset */
+
 };
 
 
@@ -850,10 +887,12 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
            return false;
          obj_coff_local_toc_table(abfd) = local_syms;
          for (i = 0; i < obj_raw_syment_count(abfd); ++i)
-           local_syms[i] = 1;
+           {
+             SET_UNALLOCATED(local_syms[i]);
+           }
        }
 
-      if (local_syms[sym] == 1
+      if (IS_UNALLOCATED(local_syms[sym])
        {
          local_syms[sym] = global_toc_size;
          ret_val = global_toc_size;
@@ -889,7 +928,7 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
 
       /* check to see if there's a toc slot allocated. If not, do it
         here. It will be used in relocate_section */
-      if (h->toc_offset == 1)
+      if (IS_UNALLOCATED(h->toc_offset))
        {
          h->toc_offset = global_toc_size;
          ret_val = global_toc_size;
@@ -975,10 +1014,12 @@ ppc_record_data_in_toc_entry(abfd, info, sec, sym, toc_kind)
            return false;
          obj_coff_local_toc_table(abfd) = local_syms;
          for (i = 0; i < obj_raw_syment_count(abfd); ++i)
-           local_syms[i] = 1;
+           {
+             SET_UNALLOCATED(local_syms[i]);
+           }
        }
 
-      if (local_syms[sym] == 1
+      if (IS_UNALLOCATED(local_syms[sym])
        {
          local_syms[sym] = global_toc_size;
          ret_val = global_toc_size;
@@ -1007,7 +1048,7 @@ ppc_record_data_in_toc_entry(abfd, info, sec, sym, toc_kind)
 
       /* check to see if there's a toc slot allocated. If not, do it
         here. It will be used in relocate_section */
-      if (h->toc_offset == 1)
+      if (IS_UNALLOCATED(h->toc_offset))
        {
 #if 0
          h->toc_offset = global_toc_size;
@@ -1348,13 +1389,13 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
                local_toc_table = obj_coff_local_toc_table(input_bfd);
                our_toc_offset = local_toc_table[symndx];
 
-               if ((our_toc_offset & 1) != 0)
+               if (IS_WRITTEN(our_toc_offset))
                  {
                    /* if it has been written out, it is marked with the 
                       1 bit. Fix up our offset, but do not write it out
                       again.
                     */
-                   our_toc_offset &= ~1;
+                   MAKE_ADDR_AGAIN(our_toc_offset);
 #ifdef TOC_DEBUG
 
                    fprintf(stderr,
@@ -1381,7 +1422,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
                               val,
                               toc_section->contents + our_toc_offset);
 
-                   local_toc_table[symndx] |= 1;
+                   MARK_AS_WRITTEN(local_toc_table[symndx]);
                    fixit = true;
                  }
              }
@@ -1392,7 +1433,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
 
                if ((r_flags & IMAGE_REL_PPC_TOCDEFN) 
                    == IMAGE_REL_PPC_TOCDEFN 
-                   && our_toc_offset == 1)
+                   && IS_UNALLOCATED(our_toc_offset))
                  {
                    /* This is unbelievable cheese. Some knowledgable asm 
                       hacker has decided to use r2 as a base for loading 
@@ -1423,13 +1464,13 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
 
                    record_toc(toc_section, our_toc_offset, pub, strdup(name));
                  }
-               else if ((our_toc_offset & 1) != 0)
+               else if (IS_WRITTEN(our_toc_offset))
                  {
                    /* if it has been written out, it is marked with the 
                       1 bit. Fix up our offset, but do not write it out
                       again.
                     */
-                   our_toc_offset &= ~1;
+                   MAKE_ADDR_AGAIN(our_toc_offset);
 #ifdef TOC_DEBUG
                    fprintf(stderr,
                            "Not writing out toc_offset of %d for %s\n", 
@@ -1457,7 +1498,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
                               val,
                               toc_section->contents + our_toc_offset);
 
-                   h->toc_offset |= 1;
+                   MARK_AS_WRITTEN(h->toc_offset);
                    /* The tricky part is that this is the address that */
                    /* needs a .reloc entry for it */
                    fixit = true;
@@ -1594,44 +1635,45 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
                  target = "__idata4_magic__";
                else if (strcmp(".idata$5", name) == 0)
                  target = "__idata5_magic__";
-               else
-                 abort();
 
-               myh = 0;
-
-               myh = coff_link_hash_lookup (coff_hash_table (info),
-                                            target,
-                                            false, false, true);
-               if (myh == 0) 
+               if (target != 0)
                  {
-                   fprintf(stderr, "Missing idata magic cookies, "
-                           "this cannot work anyway...\n");
-                   abort();
-                 }
+                   myh = 0;
 
-               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__",
+                                                target,
                                                 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;
-
-                   idata5offset = myh->root.u.def.value;
-                   myh = coff_link_hash_lookup (coff_hash_table (info),
-                                                "__idata6_magic__",
-                                                false, false, true);
-
-                   thunk_size = myh->root.u.def.value - idata5offset;
-                   myh = coff_link_hash_lookup (coff_hash_table (info),
-                                                "__idata4_magic__",
-                                                false, false, true);
-                   import_table_size = myh->root.u.def.value;
+                   if (myh == 0) 
+                     {
+                       fprintf(stderr, "Missing idata magic cookies, "
+                               "this cannot work anyway...\n");
+                       abort();
+                     }
+                   
+                   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;
+                       
+                       idata5offset = myh->root.u.def.value;
+                       myh = coff_link_hash_lookup (coff_hash_table (info),
+                                                    "__idata6_magic__",
+                                                    false, false, true);
+                       
+                       thunk_size = myh->root.u.def.value - idata5offset;
+                       myh = coff_link_hash_lookup (coff_hash_table (info),
+                                                    "__idata4_magic__",
+                                                    false, false, true);
+                       import_table_size = myh->root.u.def.value;
+                     }
                  }
              }
 
@@ -1841,7 +1883,7 @@ ppc_process_before_allocation (abfd, info)
   asection *sec;
   struct internal_reloc *i, *rel;
 
-#if DEBUG_RELOC
+#ifdef DEBUG_RELOC
   fprintf(stderr, 
          "ppc_process_before_allocation: BFD %s\n", 
          bfd_get_filename(abfd));
@@ -2175,7 +2217,7 @@ ppc_coff_rtype2howto (relent, internal)
      For now, we just strip this stuff to find the type, and ignore it other
      than that.
   */
-
+  reloc_howto_type *howto;
   unsigned short r_type  = EXTRACT_TYPE (internal->r_type);
   unsigned short r_flags = EXTRACT_FLAGS(internal->r_type);
   unsigned short junk    = EXTRACT_JUNK (internal->r_type);
@@ -2220,26 +2262,35 @@ ppc_coff_rtype2howto (relent, internal)
     case IMAGE_REL_PPC_ADDR16:
     case IMAGE_REL_PPC_REL24:
     case IMAGE_REL_PPC_ADDR24:
-    case IMAGE_REL_PPC_TOCREL16:
     case IMAGE_REL_PPC_ADDR32:
     case IMAGE_REL_PPC_IFGLUE:
     case IMAGE_REL_PPC_ADDR32NB:
     case IMAGE_REL_PPC_SECTION:
     case IMAGE_REL_PPC_SECREL:
       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
+      howto = ppc_coff_howto_table + r_type;
       break;
     case IMAGE_REL_PPC_IMGLUE:
       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
+      howto = ppc_coff_howto_table + r_type;
+      break;
+    case IMAGE_REL_PPC_TOCREL16:
+      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
+      if (r_flags & IMAGE_REL_PPC_TOCDEFN)
+       howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
+      else
+       howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
       break;
     default:
       fprintf(stderr, 
              "Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
              ppc_coff_howto_table[r_type].name,
              r_type);
+      howto = ppc_coff_howto_table + r_type;      
       break;
     }
   
-  relent->howto = ppc_coff_howto_table + r_type;
+  relent->howto = howto;
   
 }
 
@@ -2309,29 +2360,38 @@ coff_ppc_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
     case IMAGE_REL_PPC_ADDR32NB:
       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
       *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+      howto = ppc_coff_howto_table + r_type;
+      break;
+    case IMAGE_REL_PPC_TOCREL16:
+      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+      if (r_flags & IMAGE_REL_PPC_TOCDEFN)
+       howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
+      else
+       howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
       break;
     case IMAGE_REL_PPC_ADDR16:
     case IMAGE_REL_PPC_REL24:
     case IMAGE_REL_PPC_ADDR24:
-    case IMAGE_REL_PPC_TOCREL16:
     case IMAGE_REL_PPC_ADDR32:
     case IMAGE_REL_PPC_IFGLUE:
     case IMAGE_REL_PPC_SECTION:
     case IMAGE_REL_PPC_SECREL:
       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+      howto = ppc_coff_howto_table + r_type;
       break;
     case IMAGE_REL_PPC_IMGLUE:
       DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+      howto = ppc_coff_howto_table + r_type;
       break;
     default:
       fprintf(stderr, 
              "Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
              ppc_coff_howto_table[r_type].name,
              r_type);
+      howto = ppc_coff_howto_table + r_type;
       break;
     }
   
-  howto = ppc_coff_howto_table + r_type;
   return howto;
 }
 
@@ -2353,19 +2413,19 @@ ppc_coff_reloc_type_lookup (abfd, code)
   fprintf(stderr, "ppc_coff_reloc_type_lookup for %s\n",
          bfd_get_reloc_code_name(code));
 #endif
-  
+
   switch (code)
     {
+      HOW2MAP(BFD_RELOC_32_GOTOFF,    IMAGE_REL_PPC_IMGLUE);
       HOW2MAP(BFD_RELOC_16_GOT_PCREL, IMAGE_REL_PPC_IFGLUE);
       HOW2MAP(BFD_RELOC_16,           IMAGE_REL_PPC_ADDR16);
       HOW2MAP(BFD_RELOC_PPC_B26,      IMAGE_REL_PPC_REL24);
       HOW2MAP(BFD_RELOC_PPC_BA26,     IMAGE_REL_PPC_ADDR24);
       HOW2MAP(BFD_RELOC_PPC_TOC16,    IMAGE_REL_PPC_TOCREL16);
+      HOW2MAP(BFD_RELOC_16_GOTOFF,    IMAGE_REL_PPC_TOCREL16_DEFN);
       HOW2MAP(BFD_RELOC_32,           IMAGE_REL_PPC_ADDR32);
       HOW2MAP(BFD_RELOC_RVA,          IMAGE_REL_PPC_ADDR32NB);
     default: 
-      fprintf(stderr,
-             "\treturning NULL\n");
       return NULL;
     }
   
index 6dc48e57655bdd59830fd769f31341db70d114d3..d76882a3dc68af96671d8cb0cf1599d57b76928d 100644 (file)
@@ -959,6 +959,34 @@ coff_set_alignment_hook (abfd, section, scnhdr)
   ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_4BYTES,  2)
   ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_2BYTES,  1)
   ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_1BYTES,  0)
+
+#ifdef POWERPC_LE_PE
+  if (strcmp (section->name, ".idata$2") == 0)
+    {
+      fprintf(stderr, "Setting alignment for .idata$4\n");
+      section->alignment_power = 0;
+    }
+  else if (strcmp (section->name, ".idata$3") == 0)
+    {
+      fprintf(stderr, "Setting alignment for .idata$4\n");
+      section->alignment_power = 0;
+    }
+  else if (strcmp (section->name, ".idata$4") == 0)
+    {
+      fprintf(stderr, "Setting alignment for .idata$4\n");
+      section->alignment_power = 2;
+    }
+  else if (strcmp (section->name, ".idata$5") == 0)
+    {
+      fprintf(stderr, "Setting alignment for .idata$5\n");
+      section->alignment_power = 2;
+    }
+  else if (strcmp (section->name, ".idata$6") == 0)
+    {
+      fprintf(stderr, "Setting alignment for .idata$6\n");
+      section->alignment_power = 1;
+    }
+#endif
 }
 #undef ALIGN_SET
 #undef ELIFALIGN_SET