* elf32-ppc.c (ppc_elf_install_value): Delete.
(shared_stub_entry, stub_entry): Make them arrays of ints. Remove initial branch. (ppc_elf_relax_section): Write one branch around all trampolines instead. Correct bogus R_PPC_PLTREL24 handling. Correct branch range check. Only use shared_stub_entry when shared. Test that branches can reach stubs. Write trampolines out at end so that just one realloc is used. Handle little-endian mode. Move relevant code from ppc_elf_install_value to here. (ppc_elf_relocate_section): Move code handling RELAX32 from ppc_elf_install_value to here.
This commit is contained in:
parent
1be5957932
commit
9abc968f91
|
@ -1,3 +1,17 @@
|
|||
2003-11-07 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* elf32-ppc.c (ppc_elf_install_value): Delete.
|
||||
(shared_stub_entry, stub_entry): Make them arrays of ints.
|
||||
Remove initial branch.
|
||||
(ppc_elf_relax_section): Write one branch around all trampolines
|
||||
instead. Correct bogus R_PPC_PLTREL24 handling. Correct
|
||||
branch range check. Only use shared_stub_entry when shared.
|
||||
Test that branches can reach stubs. Write trampolines out at
|
||||
end so that just one realloc is used. Handle little-endian
|
||||
mode. Move relevant code from ppc_elf_install_value to here.
|
||||
(ppc_elf_relocate_section): Move code handling RELAX32 from
|
||||
ppc_elf_install_value to here.
|
||||
|
||||
2003-11-06 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* elf32-ppc.c (ppc_elf_howto_raw); Add entry for R_PPC_RELAX32PC.
|
||||
|
|
370
bfd/elf32-ppc.c
370
bfd/elf32-ppc.c
|
@ -1532,32 +1532,32 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
|
|||
FALSE), /* pcrel_offset */
|
||||
|
||||
/* Phony relocs to handle branch stubs. */
|
||||
HOWTO (R_PPC_RELAX32, /* type */
|
||||
0, /* rightshift */
|
||||
0, /* size */
|
||||
HOWTO (R_PPC_RELAX32, /* type */
|
||||
0, /* rightshift */
|
||||
0, /* size */
|
||||
0, /* bitsize */
|
||||
FALSE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_PPC_RELAX32", /* name */
|
||||
"R_PPC_RELAX32", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0, /* dst_mask */
|
||||
0, /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
|
||||
HOWTO (R_PPC_RELAX32PC, /* type */
|
||||
0, /* rightshift */
|
||||
0, /* size */
|
||||
HOWTO (R_PPC_RELAX32PC, /* type */
|
||||
0, /* rightshift */
|
||||
0, /* size */
|
||||
0, /* bitsize */
|
||||
FALSE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_PPC_RELAX32PC", /* name */
|
||||
"R_PPC_RELAX32PC", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0, /* dst_mask */
|
||||
0, /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
|
||||
/* GNU extension to record C++ vtable hierarchy. */
|
||||
|
@ -1625,84 +1625,26 @@ ppc_elf_howto_init (void)
|
|||
}
|
||||
}
|
||||
|
||||
static bfd_reloc_status_type
|
||||
ppc_elf_install_value (bfd *abfd,
|
||||
bfd_byte *hit_addr,
|
||||
bfd_vma v,
|
||||
unsigned int r_type)
|
||||
{
|
||||
bfd_vma t0, t1;
|
||||
#ifdef BFD_HOST_U_64_BIT
|
||||
BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
|
||||
#else
|
||||
bfd_vma val = v;
|
||||
#endif
|
||||
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
case R_PPC_RELAX32:
|
||||
case R_PPC_RELAX32PC:
|
||||
t0 = bfd_get_32 (abfd, hit_addr);
|
||||
t1 = bfd_get_32 (abfd, hit_addr + 4);
|
||||
|
||||
/* We're clearing the bits for R_PPC_ADDR16_HA
|
||||
and R_PPC_ADDR16_LO here. */
|
||||
t0 &= ~0xffff;
|
||||
t1 &= ~0xffff;
|
||||
|
||||
/* t0 is HA, t1 is lo */
|
||||
t0 |= ((val + 0x8000) >> 16) & 0xffff;
|
||||
t1 |= val & 0xffff;
|
||||
|
||||
bfd_put_32 (abfd, t0, hit_addr);
|
||||
bfd_put_32 (abfd, t1, hit_addr + 4);
|
||||
break;
|
||||
|
||||
case R_PPC_REL24:
|
||||
case R_PPC_LOCAL24PC:
|
||||
case R_PPC_PLTREL24:
|
||||
t0 = bfd_get_32 (abfd, hit_addr);
|
||||
t0 &= ~0x3fffffc;
|
||||
t0 |= val & 0x3fffffc;
|
||||
bfd_put_32 (abfd, t0, hit_addr);
|
||||
break;
|
||||
|
||||
case R_PPC_REL14:
|
||||
case R_PPC_REL14_BRTAKEN:
|
||||
case R_PPC_REL14_BRNTAKEN:
|
||||
t0 = bfd_get_32 (abfd, hit_addr);
|
||||
t0 &= ~0xfffc;
|
||||
t0 |= val & 0xfffc;
|
||||
bfd_put_32 (abfd, t0, hit_addr);
|
||||
break;
|
||||
|
||||
default:
|
||||
return bfd_reloc_notsupported;
|
||||
}
|
||||
|
||||
return bfd_reloc_ok;
|
||||
}
|
||||
|
||||
static const bfd_byte shared_stub_entry[] =
|
||||
static const int shared_stub_entry[] =
|
||||
{
|
||||
0x48, 0x00, 0x00, 0x24, /* b .+36 */
|
||||
0x7c, 0x08, 0x02, 0xa6, /* mflr 0 */
|
||||
0x42, 0x9f, 0x00, 0x05, /* bcl 20, 31, .Lxxx */
|
||||
0x7d, 0x68, 0x02, 0xa6, /* mflr 11 */
|
||||
0x3d, 0x6b, 0x00, 0x00, /* addis 11, 11, (xxx-.Lxxx)@ha */
|
||||
0x39, 0x6b, 0x00, 0x18, /* addi 11, 11, (xxx-.Lxxx)@l */
|
||||
0x7c, 0x08, 0x03, 0xa6, /* mtlr 0 */
|
||||
0x7d, 0x69, 0x03, 0xa6, /* mtctr 11 */
|
||||
0x4e, 0x80, 0x04, 0x20, /* bctr */
|
||||
0x7c0802a6, /* mflr 0 */
|
||||
0x429f0005, /* bcl 20, 31, .Lxxx */
|
||||
0x7d6802a6, /* mflr 11 */
|
||||
0x3d6b0000, /* addis 11, 11, (xxx-.Lxxx)@ha */
|
||||
0x396b0018, /* addi 11, 11, (xxx-.Lxxx)@l */
|
||||
0x7c0803a6, /* mtlr 0 */
|
||||
0x7d6903a6, /* mtctr 11 */
|
||||
0x4e800420, /* bctr */
|
||||
};
|
||||
|
||||
static const bfd_byte stub_entry[] =
|
||||
static const int stub_entry[] =
|
||||
{
|
||||
0x48, 0x00, 0x00, 0x14, /* b .+20 */
|
||||
0x3d, 0x60, 0x00, 0x00, /* lis 11,xxx@ha */
|
||||
0x39, 0x6b, 0x00, 0x00, /* addi 11,11,xxx@l */
|
||||
0x7d, 0x69, 0x03, 0xa6, /* mtctr 11 */
|
||||
0x4e, 0x80, 0x04, 0x20, /* bctr */
|
||||
0x3d600000, /* lis 11,xxx@ha */
|
||||
0x396b0000, /* addi 11,11,xxx@l */
|
||||
0x7d6903a6, /* mtctr 11 */
|
||||
0x4e800420, /* bctr */
|
||||
};
|
||||
|
||||
|
||||
|
@ -1726,9 +1668,9 @@ ppc_elf_relax_section (bfd *abfd,
|
|||
Elf_Internal_Rela *internal_relocs = NULL;
|
||||
Elf_Internal_Rela *irel, *irelend;
|
||||
struct one_fixup *fixups = NULL;
|
||||
bfd_boolean changed_contents = FALSE;
|
||||
bfd_boolean changed_relocs = FALSE;
|
||||
bfd_boolean changed;
|
||||
struct ppc_elf_link_hash_table *ppc_info;
|
||||
bfd_size_type trampoff;
|
||||
|
||||
*again = FALSE;
|
||||
|
||||
|
@ -1743,6 +1685,10 @@ ppc_elf_relax_section (bfd *abfd,
|
|||
if (isec->_cooked_size == 0)
|
||||
isec->_cooked_size = isec->_raw_size;
|
||||
|
||||
trampoff = (isec->_cooked_size + 3) & (bfd_vma) -4;
|
||||
/* Space for a branch around any trampolines. */
|
||||
trampoff += 4;
|
||||
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
|
||||
/* Get a copy of the native relocations. */
|
||||
|
@ -1772,21 +1718,26 @@ ppc_elf_relax_section (bfd *abfd,
|
|||
for (irel = internal_relocs; irel < irelend; irel++)
|
||||
{
|
||||
unsigned long r_type = ELF32_R_TYPE (irel->r_info);
|
||||
bfd_vma symaddr, reladdr, trampoff, toff, roff;
|
||||
bfd_vma symaddr, reladdr, toff, roff;
|
||||
asection *tsec;
|
||||
bfd_size_type amt;
|
||||
struct one_fixup *f;
|
||||
size_t insn_offset = 0;
|
||||
bfd_vma max_branch_offset;
|
||||
bfd_vma max_branch_offset, val;
|
||||
bfd_byte *hit_addr;
|
||||
unsigned long t0;
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
case R_PPC_REL24:
|
||||
case R_PPC_LOCAL24PC:
|
||||
case R_PPC_PLTREL24:
|
||||
max_branch_offset = 1 << 25;
|
||||
break;
|
||||
|
||||
case R_PPC_REL14:
|
||||
case R_PPC_REL14_BRTAKEN:
|
||||
case R_PPC_REL14_BRNTAKEN:
|
||||
case R_PPC_PLTREL24:
|
||||
max_branch_offset = 1 << 15;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1824,7 +1775,7 @@ ppc_elf_relax_section (bfd *abfd,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Need dynamic symbol handling. */
|
||||
/* Global symbol handling. */
|
||||
unsigned long indx;
|
||||
struct elf_link_hash_entry *h;
|
||||
|
||||
|
@ -1835,62 +1786,34 @@ ppc_elf_relax_section (bfd *abfd,
|
|||
|| h->root.type == bfd_link_hash_warning)
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
|
||||
if (r_type == R_PPC_PLTREL24)
|
||||
if (r_type == R_PPC_PLTREL24
|
||||
&& ppc_info->plt != NULL
|
||||
&& h->plt.offset != (bfd_vma) -1)
|
||||
{
|
||||
Elf_Internal_Sym *isym;
|
||||
|
||||
if (h->plt.offset == (bfd_vma) -1
|
||||
|| ppc_info->plt == NULL)
|
||||
{
|
||||
|
||||
/* Read this BFD's local symbols. */
|
||||
if (isymbuf == NULL)
|
||||
{
|
||||
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
|
||||
if (isymbuf == NULL)
|
||||
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
|
||||
symtab_hdr->sh_info, 0,
|
||||
NULL, NULL, NULL);
|
||||
if (isymbuf == 0)
|
||||
goto error_return;
|
||||
}
|
||||
isym = isymbuf + ELF32_R_SYM (irel->r_info);
|
||||
|
||||
if (isym->st_shndx == SHN_UNDEF)
|
||||
/* We can't do anthing with undefined symbols. */
|
||||
continue;
|
||||
else if (isym->st_shndx == SHN_ABS)
|
||||
tsec = bfd_abs_section_ptr;
|
||||
else if (isym->st_shndx == SHN_COMMON)
|
||||
tsec = bfd_com_section_ptr;
|
||||
else
|
||||
tsec = h->root.u.def.section;
|
||||
|
||||
toff = h->root.u.def.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
tsec = ppc_info->plt;
|
||||
toff = h->plt.offset;
|
||||
}
|
||||
tsec = ppc_info->plt;
|
||||
toff = h->plt.offset;
|
||||
}
|
||||
else if (h->root.type == bfd_link_hash_undefined
|
||||
|| h->root.type == bfd_link_hash_undefweak)
|
||||
continue;
|
||||
|
||||
else
|
||||
else if (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
{
|
||||
tsec = h->root.u.def.section;
|
||||
toff = h->root.u.def.value;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the branch and target are in the same section, you have
|
||||
no hope of adding stubs. We'll error out later should the
|
||||
branch overflow. */
|
||||
if (tsec == isec)
|
||||
continue;
|
||||
|
||||
toff += irel->r_addend;
|
||||
if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
|
||||
toff = _bfd_merged_section_offset (abfd, &tsec,
|
||||
elf_section_data (tsec)->sec_info,
|
||||
toff + irel->r_addend, 0);
|
||||
else
|
||||
toff += irel->r_addend;
|
||||
toff, 0);
|
||||
|
||||
symaddr = tsec->output_section->vma + tsec->output_offset + toff;
|
||||
|
||||
|
@ -1898,70 +1821,41 @@ ppc_elf_relax_section (bfd *abfd,
|
|||
|
||||
reladdr = (isec->output_section->vma
|
||||
+ isec->output_offset
|
||||
+ roff) & (bfd_vma) -4;
|
||||
+ roff);
|
||||
|
||||
/* If the branch is in range, no need to do anything. */
|
||||
max_branch_offset = 1 << 25;
|
||||
if (r_type != R_PPC_REL24
|
||||
&& r_type != R_PPC_LOCAL24PC
|
||||
&& r_type != R_PPC_PLTREL24)
|
||||
max_branch_offset = 1 << 15;
|
||||
|
||||
if ((bfd_vma) (symaddr - reladdr) + max_branch_offset
|
||||
<= 2 * max_branch_offset)
|
||||
if (symaddr - reladdr + max_branch_offset < 2 * max_branch_offset)
|
||||
continue;
|
||||
|
||||
/* If the branch and target are in the same section, you have
|
||||
no hope. We'll error out later. */
|
||||
if (tsec == isec)
|
||||
continue;
|
||||
|
||||
/* Look for an existing fixup to this address.
|
||||
??? What if the existing fixup is for a non-pic stub, and the
|
||||
new one requires a pic stub? This presumably could happen with
|
||||
a static link and a mix of R_PPC_LOCAL24PC and R_PPC_REL24
|
||||
relocs to a symbol needing long branch stubs.
|
||||
??? Why do we require R_PPC_LOCAL24PC and branches to the plt
|
||||
to have a shared branch stub? Shared branch stubs should only
|
||||
be needed when info->shared. */
|
||||
/* Look for an existing fixup to this address. */
|
||||
for (f = fixups; f ; f = f->next)
|
||||
if (f->tsec == tsec && f->toff == toff)
|
||||
break;
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
const bfd_byte *stub;
|
||||
size_t size;
|
||||
unsigned long stub_rtype;
|
||||
|
||||
if (link_info->shared
|
||||
|| tsec == ppc_info->plt
|
||||
|| r_type == R_PPC_LOCAL24PC)
|
||||
val = trampoff - roff;
|
||||
if (val >= max_branch_offset)
|
||||
/* Oh dear, we can't reach a trampoline. Don't try to add
|
||||
one. We'll report an error later. */
|
||||
continue;
|
||||
|
||||
if (link_info->shared)
|
||||
{
|
||||
stub = shared_stub_entry;
|
||||
size = sizeof (shared_stub_entry);
|
||||
insn_offset = 16;
|
||||
size = 4 * ARRAY_SIZE (shared_stub_entry);
|
||||
insn_offset = 12;
|
||||
stub_rtype = R_PPC_RELAX32PC;
|
||||
}
|
||||
else
|
||||
{
|
||||
stub = stub_entry;
|
||||
size = sizeof (stub_entry);
|
||||
insn_offset = 4;
|
||||
size = 4 * ARRAY_SIZE (stub_entry);
|
||||
insn_offset = 0;
|
||||
stub_rtype = R_PPC_RELAX32;
|
||||
}
|
||||
|
||||
/* Resize the current section to make room for the new branch. */
|
||||
trampoff = (isec->_cooked_size + 3) & (bfd_vma) - 4;
|
||||
amt = trampoff + size;
|
||||
contents = bfd_realloc (contents, amt);
|
||||
if (contents == NULL)
|
||||
abort ();
|
||||
|
||||
isec->_cooked_size = amt;
|
||||
|
||||
memcpy (contents + trampoff, stub, size);
|
||||
|
||||
/* Hijack the old relocation. Since we need two
|
||||
relocations for this use a "composite" reloc. */
|
||||
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
||||
|
@ -1975,31 +1869,95 @@ ppc_elf_relax_section (bfd *abfd,
|
|||
f->toff = toff;
|
||||
f->trampoff = trampoff;
|
||||
fixups = f;
|
||||
|
||||
trampoff += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = f->trampoff - roff;
|
||||
if (val >= max_branch_offset)
|
||||
continue;
|
||||
|
||||
/* Nop out the reloc, since we're finalizing things here. */
|
||||
irel->r_info = ELF32_R_INFO (0, R_PPC_NONE);
|
||||
}
|
||||
|
||||
/* Fix up the existing branch to hit the trampoline. Hope like
|
||||
hell this doesn't overflow too. */
|
||||
if (ppc_elf_install_value (abfd, contents + roff,
|
||||
f->trampoff - (roff & (bfd_vma) -3) + 4,
|
||||
r_type) != bfd_reloc_ok)
|
||||
abort ();
|
||||
/* Fix up the existing branch to hit the trampoline. */
|
||||
hit_addr = contents + roff;
|
||||
switch (r_type)
|
||||
{
|
||||
case R_PPC_REL24:
|
||||
case R_PPC_LOCAL24PC:
|
||||
case R_PPC_PLTREL24:
|
||||
t0 = bfd_get_32 (abfd, hit_addr);
|
||||
t0 &= ~0x3fffffc;
|
||||
t0 |= val & 0x3fffffc;
|
||||
bfd_put_32 (abfd, t0, hit_addr);
|
||||
break;
|
||||
|
||||
changed_contents = TRUE;
|
||||
changed_relocs = TRUE;
|
||||
case R_PPC_REL14:
|
||||
case R_PPC_REL14_BRTAKEN:
|
||||
case R_PPC_REL14_BRNTAKEN:
|
||||
t0 = bfd_get_32 (abfd, hit_addr);
|
||||
t0 &= ~0xfffc;
|
||||
t0 |= val & 0xfffc;
|
||||
bfd_put_32 (abfd, t0, hit_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up. */
|
||||
while (fixups)
|
||||
/* Write out the trampolines. */
|
||||
changed = fixups != NULL;
|
||||
if (fixups != NULL)
|
||||
{
|
||||
struct one_fixup *f = fixups;
|
||||
fixups = fixups->next;
|
||||
free (f);
|
||||
const int *stub;
|
||||
bfd_byte *dest;
|
||||
bfd_vma val;
|
||||
int i, size;
|
||||
|
||||
do
|
||||
{
|
||||
struct one_fixup *f = fixups;
|
||||
fixups = fixups->next;
|
||||
free (f);
|
||||
}
|
||||
while (fixups);
|
||||
|
||||
contents = bfd_realloc (contents, trampoff);
|
||||
if (contents == NULL)
|
||||
goto error_return;
|
||||
|
||||
isec->_cooked_size = (isec->_cooked_size + 3) & (bfd_vma) -4;
|
||||
/* Branch around the trampolines. */
|
||||
val = trampoff - isec->_cooked_size + 0x48000000;
|
||||
dest = contents + isec->_cooked_size;
|
||||
isec->_cooked_size = trampoff;
|
||||
bfd_put_32 (abfd, val, dest);
|
||||
dest += 4;
|
||||
|
||||
if (link_info->shared)
|
||||
{
|
||||
stub = shared_stub_entry;
|
||||
size = ARRAY_SIZE (shared_stub_entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
stub = stub_entry;
|
||||
size = ARRAY_SIZE (stub_entry);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (dest < contents + trampoff)
|
||||
{
|
||||
bfd_put_32 (abfd, stub[i], dest);
|
||||
i++;
|
||||
if (i == size)
|
||||
i = 0;
|
||||
dest += 4;
|
||||
}
|
||||
BFD_ASSERT (i == 0);
|
||||
}
|
||||
|
||||
if (isymbuf != NULL
|
||||
&& symtab_hdr->contents != (unsigned char *) isymbuf)
|
||||
{
|
||||
|
@ -2015,7 +1973,7 @@ ppc_elf_relax_section (bfd *abfd,
|
|||
if (contents != NULL
|
||||
&& elf_section_data (isec)->this_hdr.contents != contents)
|
||||
{
|
||||
if (!changed_contents && !link_info->keep_memory)
|
||||
if (!changed && !link_info->keep_memory)
|
||||
free (contents);
|
||||
else
|
||||
{
|
||||
|
@ -2026,13 +1984,13 @@ ppc_elf_relax_section (bfd *abfd,
|
|||
|
||||
if (elf_section_data (isec)->relocs != internal_relocs)
|
||||
{
|
||||
if (!changed_relocs)
|
||||
if (!changed)
|
||||
free (internal_relocs);
|
||||
else
|
||||
elf_section_data (isec)->relocs = internal_relocs;
|
||||
}
|
||||
|
||||
*again = changed_contents || changed_relocs;
|
||||
*again = changed;
|
||||
return TRUE;
|
||||
|
||||
error_return:
|
||||
|
@ -4739,7 +4697,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
symtab_hdr, relocation, sec,
|
||||
unresolved_reloc, info,
|
||||
warned);
|
||||
|
||||
|
||||
sym_name = h->root.root.string;
|
||||
}
|
||||
|
||||
|
@ -5462,8 +5420,26 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
+ rel->r_offset - 4);
|
||||
/* Fall thru */
|
||||
case R_PPC_RELAX32:
|
||||
ppc_elf_install_value (output_bfd, contents + rel->r_offset,
|
||||
relocation + addend, r_type);
|
||||
{
|
||||
unsigned long t0;
|
||||
unsigned long t1;
|
||||
|
||||
t0 = bfd_get_32 (output_bfd, contents + rel->r_offset);
|
||||
t1 = bfd_get_32 (output_bfd, contents + rel->r_offset + 4);
|
||||
|
||||
/* We're clearing the bits for R_PPC_ADDR16_HA
|
||||
and R_PPC_ADDR16_LO here. */
|
||||
t0 &= ~0xffff;
|
||||
t1 &= ~0xffff;
|
||||
|
||||
/* t0 is HA, t1 is LO */
|
||||
relocation += addend;
|
||||
t0 |= ((relocation + 0x8000) >> 16) & 0xffff;
|
||||
t1 |= relocation & 0xffff;
|
||||
|
||||
bfd_put_32 (output_bfd, t0, contents + rel->r_offset);
|
||||
bfd_put_32 (output_bfd, t1, contents + rel->r_offset + 4);
|
||||
}
|
||||
continue;
|
||||
|
||||
/* Indirect .sdata relocation. */
|
||||
|
|
Loading…
Reference in New Issue