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:
H.J. Lu 2009-11-17 19:21:53 +00:00
parent 276a961bff
commit a231ddc0b3
2 changed files with 104 additions and 11 deletions

View File

@ -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.

View File

@ -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),