mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-30 12:44:10 +08:00
2009-11-17 H.J. Lu <hongjiu.lu@intel.com>
PR ld/10955 * elfxx-ia64.c (elfNN_ia64_link_hash_table): Add max_short_sec, max_short_offset, min_short_sec and min_short_offset. (elfNN_ia64_update_short_info): New. (elfNN_ia64_relax_section): Update max_short_sec, max_short_offset, min_short_sec and min_short_offset. (elfNN_ia64_choose_gp): Use min_short_sec/max_short_sec if they are set.
This commit is contained in:
parent
276a961bff
commit
a231ddc0b3
@ -1,5 +1,16 @@
|
||||
2009-11-17 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/10955
|
||||
* elfxx-ia64.c (elfNN_ia64_link_hash_table): Add max_short_sec,
|
||||
max_short_offset, min_short_sec and min_short_offset.
|
||||
(elfNN_ia64_update_short_info): New.
|
||||
(elfNN_ia64_relax_section): Update max_short_sec,
|
||||
max_short_offset, min_short_sec and min_short_offset.
|
||||
(elfNN_ia64_choose_gp): Use min_short_sec/max_short_sec if
|
||||
they are set.
|
||||
|
||||
2009-11-17 Paul Brook <paul@codesourcery.com>
|
||||
Daniel Jacobowitz <dan@codesourcery.com>
|
||||
Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* elf32-arm.c (using_thumb_only, arch_has_arm_nop,
|
||||
arch_has_thumb2_nop): Handle TAG_CPU_ARCH_V7E_M.
|
||||
|
102
bfd/elfxx-ia64.c
102
bfd/elfxx-ia64.c
@ -172,6 +172,14 @@ struct elfNN_ia64_link_hash_table
|
||||
unsigned reltext : 1; /* are there relocs against readonly sections? */
|
||||
unsigned self_dtpmod_done : 1;/* has self DTPMOD entry been finished? */
|
||||
bfd_vma self_dtpmod_offset; /* .got offset to self DTPMOD entry */
|
||||
/* There are maybe R_IA64_GPREL22 relocations, including those
|
||||
optimized from R_IA64_LTOFF22X, against non-SHF_IA_64_SHORT
|
||||
sections. We need to record those sections so that we can choose
|
||||
a proper GP to cover all R_IA64_GPREL22 relocations. */
|
||||
asection *max_short_sec; /* maximum short section */
|
||||
bfd_vma max_short_offset; /* maximum short offset */
|
||||
asection *min_short_sec; /* minimum short section */
|
||||
bfd_vma min_short_offset; /* minimum short offset */
|
||||
|
||||
htab_t loc_hash_table;
|
||||
void *loc_hash_memory;
|
||||
@ -752,6 +760,41 @@ elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
|
||||
|
||||
/* These functions do relaxation for IA-64 ELF. */
|
||||
|
||||
static void
|
||||
elfNN_ia64_update_short_info (asection *sec, bfd_vma offset,
|
||||
struct elfNN_ia64_link_hash_table *ia64_info)
|
||||
{
|
||||
/* Skip SHF_IA_64_SHORT sections. */
|
||||
if (sec->flags & SEC_SMALL_DATA)
|
||||
return;
|
||||
|
||||
if (!ia64_info->min_short_sec)
|
||||
{
|
||||
ia64_info->max_short_sec = sec;
|
||||
ia64_info->max_short_offset = offset;
|
||||
ia64_info->min_short_sec = sec;
|
||||
ia64_info->min_short_offset = offset;
|
||||
}
|
||||
else if (sec == ia64_info->max_short_sec
|
||||
&& offset > ia64_info->max_short_offset)
|
||||
ia64_info->max_short_offset = offset;
|
||||
else if (sec == ia64_info->min_short_sec
|
||||
&& offset < ia64_info->min_short_offset)
|
||||
ia64_info->min_short_offset = offset;
|
||||
else if (sec->output_section->vma
|
||||
> ia64_info->max_short_sec->output_section->vma)
|
||||
{
|
||||
ia64_info->max_short_sec = sec;
|
||||
ia64_info->max_short_offset = offset;
|
||||
}
|
||||
else if (sec->output_section->vma
|
||||
< ia64_info->min_short_sec->output_section->vma)
|
||||
{
|
||||
ia64_info->min_short_sec = sec;
|
||||
ia64_info->min_short_offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
elfNN_ia64_relax_section (bfd *abfd, asection *sec,
|
||||
struct bfd_link_info *link_info,
|
||||
@ -855,6 +898,9 @@ elfNN_ia64_relax_section (bfd *abfd, asection *sec,
|
||||
is_branch = TRUE;
|
||||
break;
|
||||
|
||||
case R_IA64_GPREL22:
|
||||
/* Update max_short_sec/min_short_sec. */
|
||||
|
||||
case R_IA64_LTOFF22X:
|
||||
case R_IA64_LDXMOV:
|
||||
/* We can't relax ldx/mov in pass 0 since br relaxations will
|
||||
@ -1171,7 +1217,11 @@ elfNN_ia64_relax_section (bfd *abfd, asection *sec,
|
||||
||(bfd_signed_vma) (symaddr - gp) < -0x200000)
|
||||
continue;
|
||||
|
||||
if (r_type == R_IA64_LTOFF22X)
|
||||
if (r_type == R_IA64_GPREL22)
|
||||
elfNN_ia64_update_short_info (tsec,
|
||||
tsec->output_offset + toff,
|
||||
ia64_info);
|
||||
else if (r_type == R_IA64_LTOFF22X)
|
||||
{
|
||||
irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
|
||||
R_IA64_GPREL22);
|
||||
@ -1181,6 +1231,10 @@ elfNN_ia64_relax_section (bfd *abfd, asection *sec,
|
||||
dyn_i->want_gotx = 0;
|
||||
changed_got |= !dyn_i->want_got;
|
||||
}
|
||||
|
||||
elfNN_ia64_update_short_info (tsec,
|
||||
tsec->output_offset + toff,
|
||||
ia64_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4256,6 +4310,20 @@ elfNN_ia64_choose_gp (bfd *abfd, struct bfd_link_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
if (ia64_info->min_short_sec)
|
||||
{
|
||||
if (min_short_vma
|
||||
> (ia64_info->min_short_sec->output_section->vma
|
||||
+ ia64_info->min_short_offset))
|
||||
min_short_vma = (ia64_info->min_short_sec->output_section->vma
|
||||
+ ia64_info->min_short_offset);
|
||||
if (max_short_vma
|
||||
< (ia64_info->max_short_sec->output_section->vma
|
||||
+ ia64_info->max_short_offset))
|
||||
max_short_vma = (ia64_info->max_short_sec->output_section->vma
|
||||
+ ia64_info->max_short_offset);
|
||||
}
|
||||
|
||||
/* See if the user wants to force a value. */
|
||||
gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
|
||||
FALSE, FALSE);
|
||||
@ -4273,17 +4341,30 @@ elfNN_ia64_choose_gp (bfd *abfd, struct bfd_link_info *info)
|
||||
{
|
||||
/* Pick a sensible value. */
|
||||
|
||||
asection *got_sec = ia64_info->root.sgot;
|
||||
if (ia64_info->min_short_sec)
|
||||
{
|
||||
bfd_vma short_range = max_short_vma - min_short_vma;
|
||||
|
||||
/* Start with just the address of the .got. */
|
||||
if (got_sec)
|
||||
gp_val = got_sec->output_section->vma;
|
||||
else if (max_short_vma != 0)
|
||||
gp_val = min_short_vma;
|
||||
else if (max_vma - min_vma < 0x200000)
|
||||
gp_val = min_vma;
|
||||
/* If min_short_sec is set, pick one in the middle bewteen
|
||||
min_short_vma and max_short_vma. */
|
||||
if (short_range >= 0x400000)
|
||||
goto overflow;
|
||||
gp_val = min_short_vma + short_range / 2;
|
||||
}
|
||||
else
|
||||
gp_val = max_vma - 0x200000 + 8;
|
||||
{
|
||||
asection *got_sec = ia64_info->root.sgot;
|
||||
|
||||
/* Start with just the address of the .got. */
|
||||
if (got_sec)
|
||||
gp_val = got_sec->output_section->vma;
|
||||
else if (max_short_vma != 0)
|
||||
gp_val = min_short_vma;
|
||||
else if (max_vma - min_vma < 0x200000)
|
||||
gp_val = min_vma;
|
||||
else
|
||||
gp_val = max_vma - 0x200000 + 8;
|
||||
}
|
||||
|
||||
/* If it is possible to address the entire image, but we
|
||||
don't with the choice above, adjust. */
|
||||
@ -4310,6 +4391,7 @@ elfNN_ia64_choose_gp (bfd *abfd, struct bfd_link_info *info)
|
||||
{
|
||||
if (max_short_vma - min_short_vma >= 0x400000)
|
||||
{
|
||||
overflow:
|
||||
(*_bfd_error_handler)
|
||||
(_("%s: short data segment overflowed (0x%lx >= 0x400000)"),
|
||||
bfd_get_filename (abfd),
|
||||
|
Loading…
Reference in New Issue
Block a user