/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
}
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) \
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;
}
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 */
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
}
&& (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;
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:
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;
}
}
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 */
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);
+ 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);
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;
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 */
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
/* 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. */
/* 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. */