Change bookmark allocation
[binutils-gdb.git] / bfd / coff-rs6000.c
index 3248670db277e8c6c77eec98a5bfbd7d8b3f3e33..3f0753e5bfc766e5a868a15d57ba10f97925b544 100644 (file)
@@ -650,7 +650,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x00: Standard 32 bit relocation.  */
   HOWTO (R_POS,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -665,7 +665,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x01: 32 bit relocation, but store negative value.  */
   HOWTO (R_NEG,                        /* type */
         0,                     /* rightshift */
-        -2,                    /* size (0 = byte, 1 = short, 2 = long) */
+        -4,                    /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -680,7 +680,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x02: 32 bit PC relative relocation.  */
   HOWTO (R_REL,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         true,                  /* pc_relative */
         0,                     /* bitpos */
@@ -695,7 +695,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x03: 16 bit TOC relative relocation.  */
   HOWTO (R_TOC,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -710,7 +710,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x04: Same as R_TOC  */
   HOWTO (R_TRL,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -725,7 +725,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x05: External TOC relative symbol.  */
   HOWTO (R_GL,                 /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -740,7 +740,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x06: Local TOC relative symbol.   */
   HOWTO (R_TCL,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -757,7 +757,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x08: Same as R_RBA.  */
   HOWTO (R_BA,                 /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         26,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -774,7 +774,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x0a: Same as R_RBR.  */
   HOWTO (R_BR,                 /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         26,                    /* bitsize */
         true,                  /* pc_relative */
         0,                     /* bitpos */
@@ -791,7 +791,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x0c: Same as R_POS.  */
   HOWTO (R_RL,                 /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -806,7 +806,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x0d: Same as R_POS.  */
   HOWTO (R_RLA,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -823,7 +823,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x0f: Non-relocating reference.  Bitsize is 1 so that r_rsize is 0.  */
   HOWTO (R_REF,                        /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* size */
         1,                     /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -842,7 +842,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x13: Same as R_TOC.  */
   HOWTO (R_TRLA,               /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -857,7 +857,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x14: Modifiable relative branch.  */
   HOWTO (R_RRTBI,              /* type */
         1,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -872,7 +872,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x15: Modifiable absolute branch.  */
   HOWTO (R_RRTBA,              /* type */
         1,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -887,7 +887,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x16: Modifiable call absolute indirect.  */
   HOWTO (R_CAI,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -902,7 +902,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x17: Modifiable call relative.  */
   HOWTO (R_CREL,               /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -917,7 +917,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x18: Modifiable branch absolute.  */
   HOWTO (R_RBA,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         26,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -932,7 +932,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x19: Modifiable branch absolute.  */
   HOWTO (R_RBAC,               /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -947,7 +947,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x1a: Modifiable branch relative.  */
   HOWTO (R_RBR,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         26,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -962,7 +962,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x1b: Modifiable branch absolute.  */
   HOWTO (R_RBRC,               /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -977,7 +977,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x1c: 16 bit Non modifiable absolute branch.  */
   HOWTO (R_BA,                 /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -992,7 +992,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x1d: Modifiable branch relative.  */
   HOWTO (R_RBR,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         true,                  /* pc_relative */
         0,                     /* bitpos */
@@ -1007,7 +1007,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x1e: Modifiable branch relative.  */
   HOWTO (R_RBA,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1024,7 +1024,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x20: General-dynamic TLS relocation.  */
   HOWTO (R_TLS,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1039,7 +1039,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x21: Initial-exec TLS relocation.  */
   HOWTO (R_TLS_IE,             /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1054,7 +1054,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x22: Local-dynamic TLS relocation.  */
   HOWTO (R_TLS_LD,             /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1069,7 +1069,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x23: Local-exec TLS relocation.  */
   HOWTO (R_TLS_LE,             /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1084,7 +1084,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x24: TLS relocation.  */
   HOWTO (R_TLSM,               /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1100,13 +1100,13 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x25: TLS module relocation.  */
   HOWTO (R_TLSML,              /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
-        "R_TLSM",              /* name */
+        "R_TLSML",             /* name */
         true,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
@@ -1126,7 +1126,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x30: High-order 16 bit TOC relative relocation.  */
   HOWTO (R_TOCU,               /* type */
         16,                    /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1141,7 +1141,7 @@ reloc_howto_type xcoff_howto_table[] =
   /* 0x31: Low-order 16 bit TOC relative relocation.  */
   HOWTO (R_TOCL,               /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1890,18 +1890,12 @@ xcoff_write_armap_old (bfd *abfd, unsigned int elength ATTRIBUTE_UNUSED,
 }
 
 static char buff20[XCOFFARMAGBIG_ELEMENT_SIZE + 1];
-#if BFD_HOST_64BIT_LONG
-#define FMT20  "%-20ld"
-#elif defined (__MSVCRT__)
-#define FMT20  "%-20I64d"
-#else
-#define FMT20  "%-20lld"
-#endif
+#define FMT20  "%-20" PRId64
 #define FMT12  "%-12d"
 #define FMT12_OCTAL  "%-12o"
 #define FMT4  "%-4d"
 #define PRINT20(d, v) \
-  sprintf (buff20, FMT20, (bfd_uint64_t)(v)), \
+  sprintf (buff20, FMT20, (uint64_t) (v)), \
   memcpy ((void *) (d), buff20, 20)
 
 #define PRINT12(d, v) \
@@ -2937,7 +2931,8 @@ xcoff_reloc_type_noop (bfd *input_bfd ATTRIBUTE_UNUSED,
                       bfd_vma val ATTRIBUTE_UNUSED,
                       bfd_vma addend ATTRIBUTE_UNUSED,
                       bfd_vma *relocation ATTRIBUTE_UNUSED,
-                      bfd_byte *contents ATTRIBUTE_UNUSED)
+                      bfd_byte *contents ATTRIBUTE_UNUSED,
+                      struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   return true;
 }
@@ -2952,7 +2947,8 @@ xcoff_reloc_type_fail (bfd *input_bfd,
                       bfd_vma val ATTRIBUTE_UNUSED,
                       bfd_vma addend ATTRIBUTE_UNUSED,
                       bfd_vma *relocation ATTRIBUTE_UNUSED,
-                      bfd_byte *contents ATTRIBUTE_UNUSED)
+                      bfd_byte *contents ATTRIBUTE_UNUSED,
+                      struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   _bfd_error_handler
     /* xgettext: c-format */
@@ -2972,7 +2968,8 @@ xcoff_reloc_type_pos (bfd *input_bfd ATTRIBUTE_UNUSED,
                      bfd_vma val,
                      bfd_vma addend,
                      bfd_vma *relocation,
-                     bfd_byte *contents ATTRIBUTE_UNUSED)
+                     bfd_byte *contents ATTRIBUTE_UNUSED,
+                     struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   *relocation = val + addend;
   return true;
@@ -2988,7 +2985,8 @@ xcoff_reloc_type_neg (bfd *input_bfd ATTRIBUTE_UNUSED,
                      bfd_vma val,
                      bfd_vma addend,
                      bfd_vma *relocation,
-                     bfd_byte *contents ATTRIBUTE_UNUSED)
+                     bfd_byte *contents ATTRIBUTE_UNUSED,
+                     struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   *relocation = - val - addend;
   return true;
@@ -3004,7 +3002,8 @@ xcoff_reloc_type_rel (bfd *input_bfd ATTRIBUTE_UNUSED,
                      bfd_vma val,
                      bfd_vma addend,
                      bfd_vma *relocation,
-                     bfd_byte *contents ATTRIBUTE_UNUSED)
+                     bfd_byte *contents ATTRIBUTE_UNUSED,
+                     struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   howto->pc_relative = true;
 
@@ -3027,7 +3026,8 @@ xcoff_reloc_type_toc (bfd *input_bfd,
                      bfd_vma val,
                      bfd_vma addend ATTRIBUTE_UNUSED,
                      bfd_vma *relocation,
-                     bfd_byte *contents ATTRIBUTE_UNUSED)
+                     bfd_byte *contents ATTRIBUTE_UNUSED,
+                     struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   struct xcoff_link_hash_entry *h;
 
@@ -3076,7 +3076,8 @@ xcoff_reloc_type_ba (bfd *input_bfd ATTRIBUTE_UNUSED,
                     bfd_vma val,
                     bfd_vma addend,
                     bfd_vma *relocation,
-                    bfd_byte *contents ATTRIBUTE_UNUSED)
+                    bfd_byte *contents ATTRIBUTE_UNUSED,
+                    struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   howto->src_mask &= ~3;
   howto->dst_mask = howto->src_mask;
@@ -3096,10 +3097,13 @@ xcoff_reloc_type_br (bfd *input_bfd,
                     bfd_vma val,
                     bfd_vma addend,
                     bfd_vma *relocation,
-                    bfd_byte *contents)
+                    bfd_byte *contents,
+                    struct bfd_link_info *info)
 {
   struct xcoff_link_hash_entry *h;
   bfd_vma section_offset;
+  struct xcoff_stub_hash_entry *stub_entry = NULL;
+  enum xcoff_stub_type stub_type;
 
   if (0 > rel->r_symndx)
     return false;
@@ -3153,6 +3157,27 @@ xcoff_reloc_type_br (bfd *input_bfd,
       howto->complain_on_overflow = complain_overflow_dont;
     }
 
+  /* Check if a stub is needed.  */
+  stub_type = bfd_xcoff_type_of_stub (input_section, rel, val, h);
+  if (stub_type != xcoff_stub_none)
+    {
+      asection *stub_csect;
+
+      stub_entry = bfd_xcoff_get_stub_entry (input_section, h, info);
+      if (stub_entry == NULL)
+       {
+         _bfd_error_handler (_("Unable to find the stub entry targeting %s"),
+                             h->root.root.string);
+         bfd_set_error (bfd_error_bad_value);
+         return false;
+       }
+
+      stub_csect = stub_entry->hcsect->root.u.def.section;
+      val = (stub_entry->stub_offset
+            + stub_csect->output_section->vma
+            + stub_csect->output_offset);
+    }
+
   /* The original PC-relative relocation is biased by -r_vaddr, so adding
      the value below will give the absolute target address.  */
   *relocation = val + addend + rel->r_vaddr;
@@ -3202,7 +3227,8 @@ xcoff_reloc_type_crel (bfd *input_bfd ATTRIBUTE_UNUSED,
                       bfd_vma val ATTRIBUTE_UNUSED,
                       bfd_vma addend,
                       bfd_vma *relocation,
-                      bfd_byte *contents ATTRIBUTE_UNUSED)
+                      bfd_byte *contents ATTRIBUTE_UNUSED,
+                      struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   howto->pc_relative = true;
   howto->src_mask &= ~3;
@@ -3227,7 +3253,8 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED,
                      bfd_vma val,
                      bfd_vma addend,
                      bfd_vma *relocation,
-                     bfd_byte *contents ATTRIBUTE_UNUSED)
+                     bfd_byte *contents ATTRIBUTE_UNUSED,
+                     struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   struct xcoff_link_hash_entry *h;
 
@@ -3236,37 +3263,26 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED,
 
   h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
 
-  /* FIXME: R_TLSML is targeting a internal TOC symbol, which will
-     make the following checks failing. It should be moved with
-     R_TLSM bellow once it works.  */
+  /* R_TLSML is handled by the loader but must be from a
+     TOC entry targeting itslef.  This is already verified in
+     xcoff_link_add_symbols.
+     The value must be 0.  */
   if (howto->type == R_TLSML)
     {
       *relocation = 0;
       return true;
     }
 
-  /* FIXME: h is sometimes null, if the TLS symbol is not exported.  */
-  if (!h)
-    {
-      char vaddr_buf[128];
-
-      sprintf_vma (vaddr_buf, rel->r_vaddr);
-      _bfd_error_handler
-       (_("%pB: TLS relocation at 0x%s over internal symbols (C_HIDEXT) not yet possible\n"),
-        input_bfd, vaddr_buf);
-      return false;
-    }
-
+  /* The target symbol should always be available even if it's not
+     exported.  */
+  BFD_ASSERT (h != NULL);
 
   /* TLS relocations must target a TLS symbol.  */
   if (h->smclas != XMC_TL && h->smclas != XMC_UL)
     {
-      char vaddr_buf[128];
-
-      sprintf_vma (vaddr_buf, rel->r_vaddr);
       _bfd_error_handler
-       (_("%pB: TLS relocation at 0x%s over non-TLS symbol %s (0x%x)\n"),
-        input_bfd, vaddr_buf, h->root.root.string, h->smclas);
+       (_("%pB: TLS relocation at 0x%" PRIx64 " over non-TLS symbol %s (0x%x)\n"),
+        input_bfd, (uint64_t) rel->r_vaddr, h->root.root.string, h->smclas);
       return false;
     }
 
@@ -3277,18 +3293,14 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED,
        && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
          || (h->flags & XCOFF_IMPORT) != 0))
     {
-      char vaddr_buf[128];
-
-      sprintf_vma (vaddr_buf, rel->r_vaddr);
       _bfd_error_handler
-       (_("%pB: TLS local relocation at 0x%s over imported symbol %s\n"),
-        input_bfd, vaddr_buf, h->root.root.string);
+       (_("%pB: TLS local relocation at 0x%" PRIx64 " over imported symbol %s\n"),
+        input_bfd, (uint64_t) rel->r_vaddr, h->root.root.string);
       return false;
     }
 
-  /* R_TLSM and R_TLSML are relocations used by the loader.
-     The value must be 0.
-     FIXME: move R_TLSML here.  */
+  /* R_TLSM are relocations used by the loader.
+     The value must be 0.  */
   if (howto->type == R_TLSM)
     {
       *relocation = 0;
@@ -3621,10 +3633,10 @@ xcoff_complain_overflow_unsigned_func (bfd *input_bfd,
    R_TLS_LE:
    Thread-local storage relocation using local-exec model.
 
-   R_TLS:
+   R_TLSM:
    Tread-local storage relocation used by the loader.
 
-   R_TLSM:
+   R_TLSML:
    Tread-local storage relocation used by the loader.
 
    R_TOCU:
@@ -3682,20 +3694,15 @@ xcoff_ppc_relocate_section (bfd *output_bfd,
            case R_POS:
            case R_NEG:
              howto.bitsize = (rel->r_size & 0x1f) + 1;
-             howto.size = howto.bitsize > 16 ? 2 : 1;
+             howto.size = HOWTO_RSIZE (howto.bitsize > 16 ? 4 : 2);
              howto.src_mask = howto.dst_mask = N_ONES (howto.bitsize);
              break;
 
            default:
-             {
-               char vaddr_buf[128];
-
-               sprintf_vma (vaddr_buf, rel->r_vaddr);
-               _bfd_error_handler
-                 (_("%pB: relocation (%d) at 0x%s has wrong r_rsize (0x%x)\n"),
-                  input_bfd, rel->r_type, vaddr_buf, rel->r_size);
-               return false;
-             }
+             _bfd_error_handler
+               (_("%pB: relocation (%d) at 0x%" PRIx64 " has wrong r_rsize (0x%x)\n"),
+                input_bfd, rel->r_type, (uint64_t) rel->r_vaddr, rel->r_size);
+             return false;
            }
        }
 
@@ -3772,7 +3779,7 @@ xcoff_ppc_relocate_section (bfd *output_bfd,
       if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
          || !((*xcoff_calculate_relocation[rel->r_type])
               (input_bfd, input_section, output_bfd, rel, sym, &howto, val,
-               addend, &relocation, contents)))
+               addend, &relocation, contents, info)))
        return false;
 
       /* address */
@@ -3783,7 +3790,7 @@ xcoff_ppc_relocate_section (bfd *output_bfd,
        abort ();
 
       /* Get the value we are going to relocate.  */
-      if (1 == howto.size)
+      if (2 == bfd_get_reloc_size (&howto))
        value_to_relocate = bfd_get_16 (input_bfd, location);
       else
        value_to_relocate = bfd_get_32 (input_bfd, location);
@@ -3830,7 +3837,7 @@ xcoff_ppc_relocate_section (bfd *output_bfd,
                               + relocation) & howto.dst_mask));
 
       /* Put the value back in the object file.  */
-      if (1 == howto.size)
+      if (2 == bfd_get_reloc_size (&howto))
        bfd_put_16 (input_bfd, value_to_relocate, location);
       else
        bfd_put_32 (input_bfd, value_to_relocate, location);
@@ -3890,8 +3897,8 @@ _bfd_xcoff_put_ldsymbol_name (bfd *abfd ATTRIBUTE_UNUSED,
          ldinfo->strings = newstrings;
        }
 
-      bfd_put_16 (ldinfo->output_bfd, (bfd_vma) (len + 1),
-                 ldinfo->strings + ldinfo->string_size);
+      ldinfo->strings[ldinfo->string_size] = ((len + 1) >> 8) & 0xff;
+      ldinfo->strings[ldinfo->string_size + 1] = ((len + 1)) & 0xff;
       strcpy (ldinfo->strings + ldinfo->string_size + 2, name);
       ldsym->_l._l_l._l_zeroes = 0;
       ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
@@ -4278,7 +4285,7 @@ xcoff_generate_rtinit  (bfd *abfd, const char *init, const char *fini,
 static reloc_howto_type xcoff_dynamic_reloc =
 HOWTO (0,                      /* type */
        0,                      /* rightshift */
-       2,                      /* size (0 = byte, 1 = short, 2 = long) */
+       4,                      /* size */
        32,                     /* bitsize */
        false,                  /* pc_relative */
        0,                      /* bitpos */
@@ -4290,6 +4297,34 @@ HOWTO (0,                        /* type */
        0xffffffff,             /* dst_mask */
        false);                 /* pcrel_offset */
 
+/* Indirect call stub
+   The first word of the code must be modified by filling in
+   the correct TOC offset.  */
+
+static const unsigned long xcoff_stub_indirect_call_code[4] =
+  {
+    0x81820000,        /* lwz r12,0(r2) */
+    0x800c0000,        /* lwz r0,0(r12) */
+    0x7c0903a6,        /* mtctr r0 */
+    0x4e800420,        /* bctr */
+  };
+
+/*  Shared call stub
+    The first word of the code must be modified by filling in
+    the correct TOC offset.
+    This is exactly as the glink code but without the traceback,
+    as it won't be an independent function.  */
+
+static const unsigned long xcoff_stub_shared_call_code[6] =
+  {
+    0x81820000,        /* lwz r12,0(r2) */
+    0x90410014,        /* stw r2,20(r1) */
+    0x800c0000,        /* lwz r0,0(r12) */
+    0x804c0004,        /* lwz r2,4(r12) */
+    0x7c0903a6,        /* mtctr r0 */
+    0x4e800420,        /* bctr */
+  };
+
 /*  glink
 
    The first word of global linkage code must be modified by filling in
@@ -4506,6 +4541,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
     /* rtinit */
     64,                                /* _xcoff_rtinit_size */
     xcoff_generate_rtinit,
+
+    /* Stub indirect call.  */
+    &xcoff_stub_indirect_call_code[0],
+    16,                                /* _xcoff_stub_indirect_call_size */
+
+    /* Stub shared call.  */
+    &xcoff_stub_shared_call_code[0],
+    24,                                /* _xcoff_stub_shared_call_size */
   };
 
 /* The transfer vector that leads the outside world to all of the above.  */
@@ -4688,6 +4731,14 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data =
     /* rtinit */
     0,                         /* _xcoff_rtinit_size */
     xcoff_generate_rtinit,
+
+    /* Stub indirect call.  */
+    &xcoff_stub_indirect_call_code[0],
+    16,                                /* _xcoff_stub_indirect_call_size */
+
+    /* Stub shared call.  */
+    &xcoff_stub_shared_call_code[0],
+    24,                                /* _xcoff_stub_shared_call_size */
   };
 
 /* The transfer vector that leads the outside world to all of the above.  */