bfd: move xcoff64_ppc_relocate_section after the HOWTO table
This will be needed for later commits, as xcoff64_ppc_relocate_section will use the HOWTO table unlike now. * coff64-rs6000.c (xcoff64_ppc_relocate_section): Move.
This commit is contained in:
parent
6d4d932867
commit
0c929e83c1
@ -1,3 +1,7 @@
|
|||||||
|
2021-03-12 Clément Chigot <clement.chigot@atos.net>
|
||||||
|
|
||||||
|
* coff64-rs6000.c (xcoff64_ppc_relocate_section): Move.
|
||||||
|
|
||||||
2021-03-12 Clément Chigot <clement.chigot@atos.net>
|
2021-03-12 Clément Chigot <clement.chigot@atos.net>
|
||||||
|
|
||||||
* coff64-rs6000.c (xcoff64_write_object_contents): Remove.
|
* coff64-rs6000.c (xcoff64_write_object_contents): Remove.
|
||||||
|
@ -814,194 +814,6 @@ xcoff64_reloc_type_br (bfd *input_bfd,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the relocation function for the PowerPC64.
|
|
||||||
See xcoff_ppc_relocation_section for more information. */
|
|
||||||
|
|
||||||
bfd_boolean
|
|
||||||
xcoff64_ppc_relocate_section (bfd *output_bfd,
|
|
||||||
struct bfd_link_info *info,
|
|
||||||
bfd *input_bfd,
|
|
||||||
asection *input_section,
|
|
||||||
bfd_byte *contents,
|
|
||||||
struct internal_reloc *relocs,
|
|
||||||
struct internal_syment *syms,
|
|
||||||
asection **sections)
|
|
||||||
{
|
|
||||||
struct internal_reloc *rel;
|
|
||||||
struct internal_reloc *relend;
|
|
||||||
|
|
||||||
rel = relocs;
|
|
||||||
relend = rel + input_section->reloc_count;
|
|
||||||
for (; rel < relend; rel++)
|
|
||||||
{
|
|
||||||
long symndx;
|
|
||||||
struct xcoff_link_hash_entry *h;
|
|
||||||
struct internal_syment *sym;
|
|
||||||
bfd_vma addend;
|
|
||||||
bfd_vma val;
|
|
||||||
struct reloc_howto_struct howto;
|
|
||||||
bfd_vma relocation;
|
|
||||||
bfd_vma value_to_relocate;
|
|
||||||
bfd_vma address;
|
|
||||||
bfd_byte *location;
|
|
||||||
|
|
||||||
/* Relocation type R_REF is a special relocation type which is
|
|
||||||
merely used to prevent garbage collection from occurring for
|
|
||||||
the csect including the symbol which it references. */
|
|
||||||
if (rel->r_type == R_REF)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* howto */
|
|
||||||
howto.type = rel->r_type;
|
|
||||||
howto.rightshift = 0;
|
|
||||||
howto.bitsize = (rel->r_size & 0x3f) + 1;
|
|
||||||
howto.size = howto.bitsize > 16 ? (howto.bitsize > 32 ? 4 : 2) : 1;
|
|
||||||
howto.pc_relative = FALSE;
|
|
||||||
howto.bitpos = 0;
|
|
||||||
howto.complain_on_overflow = (rel->r_size & 0x80
|
|
||||||
? complain_overflow_signed
|
|
||||||
: complain_overflow_bitfield);
|
|
||||||
howto.special_function = NULL;
|
|
||||||
howto.name = "internal";
|
|
||||||
howto.partial_inplace = TRUE;
|
|
||||||
howto.src_mask = howto.dst_mask = N_ONES (howto.bitsize);
|
|
||||||
howto.pcrel_offset = FALSE;
|
|
||||||
|
|
||||||
/* symbol */
|
|
||||||
val = 0;
|
|
||||||
addend = 0;
|
|
||||||
h = NULL;
|
|
||||||
sym = NULL;
|
|
||||||
symndx = rel->r_symndx;
|
|
||||||
|
|
||||||
if (-1 != symndx)
|
|
||||||
{
|
|
||||||
asection *sec;
|
|
||||||
|
|
||||||
h = obj_xcoff_sym_hashes (input_bfd)[symndx];
|
|
||||||
sym = syms + symndx;
|
|
||||||
addend = - sym->n_value;
|
|
||||||
|
|
||||||
if (NULL == h)
|
|
||||||
{
|
|
||||||
sec = sections[symndx];
|
|
||||||
/* Hack to make sure we use the right TOC anchor value
|
|
||||||
if this reloc is against the TOC anchor. */
|
|
||||||
if (sec->name[3] == '0'
|
|
||||||
&& strcmp (sec->name, ".tc0") == 0)
|
|
||||||
val = xcoff_data (output_bfd)->toc;
|
|
||||||
else
|
|
||||||
val = (sec->output_section->vma
|
|
||||||
+ sec->output_offset
|
|
||||||
+ sym->n_value
|
|
||||||
- sec->vma);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (info->unresolved_syms_in_objects != RM_IGNORE
|
|
||||||
&& (h->flags & XCOFF_WAS_UNDEFINED) != 0)
|
|
||||||
info->callbacks->undefined_symbol
|
|
||||||
(info, h->root.root.string, input_bfd, input_section,
|
|
||||||
rel->r_vaddr - input_section->vma,
|
|
||||||
info->unresolved_syms_in_objects == RM_DIAGNOSE
|
|
||||||
&& !info->warn_unresolved_syms);
|
|
||||||
|
|
||||||
if (h->root.type == bfd_link_hash_defined
|
|
||||||
|| h->root.type == bfd_link_hash_defweak)
|
|
||||||
{
|
|
||||||
sec = h->root.u.def.section;
|
|
||||||
val = (h->root.u.def.value
|
|
||||||
+ sec->output_section->vma
|
|
||||||
+ sec->output_offset);
|
|
||||||
}
|
|
||||||
else if (h->root.type == bfd_link_hash_common)
|
|
||||||
{
|
|
||||||
sec = h->root.u.c.p->section;
|
|
||||||
val = (sec->output_section->vma
|
|
||||||
+ sec->output_offset);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BFD_ASSERT (bfd_link_relocatable (info)
|
|
||||||
|| (h->flags & XCOFF_DEF_DYNAMIC) != 0
|
|
||||||
|| (h->flags & XCOFF_IMPORT) != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
|
|
||||||
|| !((*xcoff64_calculate_relocation[rel->r_type])
|
|
||||||
(input_bfd, input_section, output_bfd, rel, sym, &howto, val,
|
|
||||||
addend, &relocation, contents)))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* address */
|
|
||||||
address = rel->r_vaddr - input_section->vma;
|
|
||||||
location = contents + address;
|
|
||||||
|
|
||||||
if (address > input_section->size)
|
|
||||||
abort ();
|
|
||||||
|
|
||||||
/* Get the value we are going to relocate. */
|
|
||||||
if (1 == howto.size)
|
|
||||||
value_to_relocate = bfd_get_16 (input_bfd, location);
|
|
||||||
else if (2 == howto.size)
|
|
||||||
value_to_relocate = bfd_get_32 (input_bfd, location);
|
|
||||||
else
|
|
||||||
value_to_relocate = bfd_get_64 (input_bfd, location);
|
|
||||||
|
|
||||||
/* overflow.
|
|
||||||
|
|
||||||
FIXME: We may drop bits during the addition
|
|
||||||
which we don't check for. We must either check at every single
|
|
||||||
operation, which would be tedious, or we must do the computations
|
|
||||||
in a type larger than bfd_vma, which would be inefficient. */
|
|
||||||
|
|
||||||
if (((*xcoff_complain_overflow[howto.complain_on_overflow])
|
|
||||||
(input_bfd, value_to_relocate, relocation, &howto)))
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
char buf[SYMNMLEN + 1];
|
|
||||||
char reloc_type_name[10];
|
|
||||||
|
|
||||||
if (symndx == -1)
|
|
||||||
{
|
|
||||||
name = "*ABS*";
|
|
||||||
}
|
|
||||||
else if (h != NULL)
|
|
||||||
{
|
|
||||||
name = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
|
|
||||||
if (name == NULL)
|
|
||||||
name = "UNKNOWN";
|
|
||||||
}
|
|
||||||
sprintf (reloc_type_name, "0x%02x", rel->r_type);
|
|
||||||
|
|
||||||
(*info->callbacks->reloc_overflow)
|
|
||||||
(info, (h ? &h->root : NULL), name, reloc_type_name,
|
|
||||||
(bfd_vma) 0, input_bfd, input_section,
|
|
||||||
rel->r_vaddr - input_section->vma);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add RELOCATION to the right bits of VALUE_TO_RELOCATE. */
|
|
||||||
value_to_relocate = ((value_to_relocate & ~howto.dst_mask)
|
|
||||||
| (((value_to_relocate & howto.src_mask)
|
|
||||||
+ relocation) & howto.dst_mask));
|
|
||||||
|
|
||||||
/* Put the value back in the object file. */
|
|
||||||
if (1 == howto.size)
|
|
||||||
bfd_put_16 (input_bfd, value_to_relocate, location);
|
|
||||||
else if (2 == howto.size)
|
|
||||||
bfd_put_32 (input_bfd, value_to_relocate, location);
|
|
||||||
else
|
|
||||||
bfd_put_64 (input_bfd, value_to_relocate, location);
|
|
||||||
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The XCOFF reloc table. Actually, XCOFF relocations specify the
|
/* The XCOFF reloc table. Actually, XCOFF relocations specify the
|
||||||
@ -1496,6 +1308,196 @@ xcoff64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is the relocation function for the PowerPC64.
|
||||||
|
See xcoff_ppc_relocation_section for more information. */
|
||||||
|
|
||||||
|
bfd_boolean
|
||||||
|
xcoff64_ppc_relocate_section (bfd *output_bfd,
|
||||||
|
struct bfd_link_info *info,
|
||||||
|
bfd *input_bfd,
|
||||||
|
asection *input_section,
|
||||||
|
bfd_byte *contents,
|
||||||
|
struct internal_reloc *relocs,
|
||||||
|
struct internal_syment *syms,
|
||||||
|
asection **sections)
|
||||||
|
{
|
||||||
|
struct internal_reloc *rel;
|
||||||
|
struct internal_reloc *relend;
|
||||||
|
|
||||||
|
rel = relocs;
|
||||||
|
relend = rel + input_section->reloc_count;
|
||||||
|
for (; rel < relend; rel++)
|
||||||
|
{
|
||||||
|
long symndx;
|
||||||
|
struct xcoff_link_hash_entry *h;
|
||||||
|
struct internal_syment *sym;
|
||||||
|
bfd_vma addend;
|
||||||
|
bfd_vma val;
|
||||||
|
struct reloc_howto_struct howto;
|
||||||
|
bfd_vma relocation;
|
||||||
|
bfd_vma value_to_relocate;
|
||||||
|
bfd_vma address;
|
||||||
|
bfd_byte *location;
|
||||||
|
|
||||||
|
/* Relocation type R_REF is a special relocation type which is
|
||||||
|
merely used to prevent garbage collection from occurring for
|
||||||
|
the csect including the symbol which it references. */
|
||||||
|
if (rel->r_type == R_REF)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* howto */
|
||||||
|
howto.type = rel->r_type;
|
||||||
|
howto.rightshift = 0;
|
||||||
|
howto.bitsize = (rel->r_size & 0x3f) + 1;
|
||||||
|
howto.size = howto.bitsize > 16 ? (howto.bitsize > 32 ? 4 : 2) : 1;
|
||||||
|
howto.pc_relative = FALSE;
|
||||||
|
howto.bitpos = 0;
|
||||||
|
howto.complain_on_overflow = (rel->r_size & 0x80
|
||||||
|
? complain_overflow_signed
|
||||||
|
: complain_overflow_bitfield);
|
||||||
|
howto.special_function = NULL;
|
||||||
|
howto.name = "internal";
|
||||||
|
howto.partial_inplace = TRUE;
|
||||||
|
howto.src_mask = howto.dst_mask = N_ONES (howto.bitsize);
|
||||||
|
howto.pcrel_offset = FALSE;
|
||||||
|
|
||||||
|
/* symbol */
|
||||||
|
val = 0;
|
||||||
|
addend = 0;
|
||||||
|
h = NULL;
|
||||||
|
sym = NULL;
|
||||||
|
symndx = rel->r_symndx;
|
||||||
|
|
||||||
|
if (-1 != symndx)
|
||||||
|
{
|
||||||
|
asection *sec;
|
||||||
|
|
||||||
|
h = obj_xcoff_sym_hashes (input_bfd)[symndx];
|
||||||
|
sym = syms + symndx;
|
||||||
|
addend = - sym->n_value;
|
||||||
|
|
||||||
|
if (NULL == h)
|
||||||
|
{
|
||||||
|
sec = sections[symndx];
|
||||||
|
/* Hack to make sure we use the right TOC anchor value
|
||||||
|
if this reloc is against the TOC anchor. */
|
||||||
|
if (sec->name[3] == '0'
|
||||||
|
&& strcmp (sec->name, ".tc0") == 0)
|
||||||
|
val = xcoff_data (output_bfd)->toc;
|
||||||
|
else
|
||||||
|
val = (sec->output_section->vma
|
||||||
|
+ sec->output_offset
|
||||||
|
+ sym->n_value
|
||||||
|
- sec->vma);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (info->unresolved_syms_in_objects != RM_IGNORE
|
||||||
|
&& (h->flags & XCOFF_WAS_UNDEFINED) != 0)
|
||||||
|
info->callbacks->undefined_symbol
|
||||||
|
(info, h->root.root.string, input_bfd, input_section,
|
||||||
|
rel->r_vaddr - input_section->vma,
|
||||||
|
info->unresolved_syms_in_objects == RM_DIAGNOSE
|
||||||
|
&& !info->warn_unresolved_syms);
|
||||||
|
|
||||||
|
if (h->root.type == bfd_link_hash_defined
|
||||||
|
|| h->root.type == bfd_link_hash_defweak)
|
||||||
|
{
|
||||||
|
sec = h->root.u.def.section;
|
||||||
|
val = (h->root.u.def.value
|
||||||
|
+ sec->output_section->vma
|
||||||
|
+ sec->output_offset);
|
||||||
|
}
|
||||||
|
else if (h->root.type == bfd_link_hash_common)
|
||||||
|
{
|
||||||
|
sec = h->root.u.c.p->section;
|
||||||
|
val = (sec->output_section->vma
|
||||||
|
+ sec->output_offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BFD_ASSERT (bfd_link_relocatable (info)
|
||||||
|
|| (h->flags & XCOFF_DEF_DYNAMIC) != 0
|
||||||
|
|| (h->flags & XCOFF_IMPORT) != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
|
||||||
|
|| !((*xcoff64_calculate_relocation[rel->r_type])
|
||||||
|
(input_bfd, input_section, output_bfd, rel, sym, &howto, val,
|
||||||
|
addend, &relocation, contents)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* address */
|
||||||
|
address = rel->r_vaddr - input_section->vma;
|
||||||
|
location = contents + address;
|
||||||
|
|
||||||
|
if (address > input_section->size)
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
/* Get the value we are going to relocate. */
|
||||||
|
if (1 == howto.size)
|
||||||
|
value_to_relocate = bfd_get_16 (input_bfd, location);
|
||||||
|
else if (2 == howto.size)
|
||||||
|
value_to_relocate = bfd_get_32 (input_bfd, location);
|
||||||
|
else
|
||||||
|
value_to_relocate = bfd_get_64 (input_bfd, location);
|
||||||
|
|
||||||
|
/* overflow.
|
||||||
|
|
||||||
|
FIXME: We may drop bits during the addition
|
||||||
|
which we don't check for. We must either check at every single
|
||||||
|
operation, which would be tedious, or we must do the computations
|
||||||
|
in a type larger than bfd_vma, which would be inefficient. */
|
||||||
|
|
||||||
|
if (((*xcoff_complain_overflow[howto.complain_on_overflow])
|
||||||
|
(input_bfd, value_to_relocate, relocation, &howto)))
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
char buf[SYMNMLEN + 1];
|
||||||
|
char reloc_type_name[10];
|
||||||
|
|
||||||
|
if (symndx == -1)
|
||||||
|
{
|
||||||
|
name = "*ABS*";
|
||||||
|
}
|
||||||
|
else if (h != NULL)
|
||||||
|
{
|
||||||
|
name = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
|
||||||
|
if (name == NULL)
|
||||||
|
name = "UNKNOWN";
|
||||||
|
}
|
||||||
|
sprintf (reloc_type_name, "0x%02x", rel->r_type);
|
||||||
|
|
||||||
|
(*info->callbacks->reloc_overflow)
|
||||||
|
(info, (h ? &h->root : NULL), name, reloc_type_name,
|
||||||
|
(bfd_vma) 0, input_bfd, input_section,
|
||||||
|
rel->r_vaddr - input_section->vma);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add RELOCATION to the right bits of VALUE_TO_RELOCATE. */
|
||||||
|
value_to_relocate = ((value_to_relocate & ~howto.dst_mask)
|
||||||
|
| (((value_to_relocate & howto.src_mask)
|
||||||
|
+ relocation) & howto.dst_mask));
|
||||||
|
|
||||||
|
/* Put the value back in the object file. */
|
||||||
|
if (1 == howto.size)
|
||||||
|
bfd_put_16 (input_bfd, value_to_relocate, location);
|
||||||
|
else if (2 == howto.size)
|
||||||
|
bfd_put_32 (input_bfd, value_to_relocate, location);
|
||||||
|
else
|
||||||
|
bfd_put_64 (input_bfd, value_to_relocate, location);
|
||||||
|
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* PR 21786: The PE/COFF standard does not require NUL termination for any of
|
/* PR 21786: The PE/COFF standard does not require NUL termination for any of
|
||||||
the ASCII fields in the archive headers. So in order to be able to extract
|
the ASCII fields in the archive headers. So in order to be able to extract
|
||||||
numerical values we provide our own versions of strtol and strtoll which
|
numerical values we provide our own versions of strtol and strtoll which
|
||||||
|
Loading…
Reference in New Issue
Block a user