[GOLD] PPC64_OPT_LOCALENTRY is incompatible with tail calls
Gold version of commit 3cd7c7d7ef
.
* powerpc.cc (Target_powerpc): Rename power10_stubs_ to
power10_relocs_.
(Target_powerpc::set_power10_relocs): New accessor.
(Target_powerpc::set_power10_stubs): Delete.
(Target_powerpc::power10_stubs): Adjust.
(Target_powerpc::has_localentry0): New accessor.
(ld_0_11): New constant.
(glink_eh_frame_fde_64v1, glink_eh_frame_fde_64v2): Adjust.
(glink_eh_frame_fde_64v2_localentry0): New.
(Output_data_glink::pltresolve_size): Update.
(Output_data_glink::add_eh_frame): Use localentry0 version eh_frame.
(Output_data_glink::do_write): Move r2 save to start of ELFv2 stub
and only emit for has_localentry0. Don't use r2 in the stub.
(Target_powerpc::Scan::local, global): Adjust for
set_power10_relocs renaming.
(Target_powerpc::scan_relocs): Warn and reset plt_localentry0_.
This commit is contained in:
parent
3cd7c7d7ef
commit
63e5eea234
@ -1,3 +1,22 @@
|
|||||||
|
2020-09-26 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* powerpc.cc (Target_powerpc): Rename power10_stubs_ to
|
||||||
|
power10_relocs_.
|
||||||
|
(Target_powerpc::set_power10_relocs): New accessor.
|
||||||
|
(Target_powerpc::set_power10_stubs): Delete.
|
||||||
|
(Target_powerpc::power10_stubs): Adjust.
|
||||||
|
(Target_powerpc::has_localentry0): New accessor.
|
||||||
|
(ld_0_11): New constant.
|
||||||
|
(glink_eh_frame_fde_64v1, glink_eh_frame_fde_64v2): Adjust.
|
||||||
|
(glink_eh_frame_fde_64v2_localentry0): New.
|
||||||
|
(Output_data_glink::pltresolve_size): Update.
|
||||||
|
(Output_data_glink::add_eh_frame): Use localentry0 version eh_frame.
|
||||||
|
(Output_data_glink::do_write): Move r2 save to start of ELFv2 stub
|
||||||
|
and only emit for has_localentry0. Don't use r2 in the stub.
|
||||||
|
(Target_powerpc::Scan::local, global): Adjust for
|
||||||
|
set_power10_relocs renaming.
|
||||||
|
(Target_powerpc::scan_relocs): Warn and reset plt_localentry0_.
|
||||||
|
|
||||||
2020-09-24 Alan Modra <amodra@gmail.com>
|
2020-09-24 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* powerpc.cc (Target_powerpc::Relocate::relocate): Don't skip
|
* powerpc.cc (Target_powerpc::Relocate::relocate): Don't skip
|
||||||
|
@ -647,7 +647,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
glink_(NULL), rela_dyn_(NULL), copy_relocs_(),
|
glink_(NULL), rela_dyn_(NULL), copy_relocs_(),
|
||||||
tlsld_got_offset_(-1U),
|
tlsld_got_offset_(-1U),
|
||||||
stub_tables_(), branch_lookup_table_(), branch_info_(), tocsave_loc_(),
|
stub_tables_(), branch_lookup_table_(), branch_info_(), tocsave_loc_(),
|
||||||
power10_stubs_(false), plt_thread_safe_(false), plt_localentry0_(false),
|
power10_relocs_(false), plt_thread_safe_(false), plt_localentry0_(false),
|
||||||
plt_localentry0_init_(false), has_localentry0_(false),
|
plt_localentry0_init_(false), has_localentry0_(false),
|
||||||
has_tls_get_addr_opt_(false),
|
has_tls_get_addr_opt_(false),
|
||||||
tprel_opt_(parameters->options().tls_optimize()),
|
tprel_opt_(parameters->options().tls_optimize()),
|
||||||
@ -1079,16 +1079,18 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
sym->set_dynsym_index(-1U);
|
sym->set_dynsym_index(-1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_power10_relocs()
|
||||||
|
{
|
||||||
|
this->power10_relocs_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
power10_stubs() const
|
power10_stubs() const
|
||||||
{ return this->power10_stubs_; }
|
|
||||||
|
|
||||||
void
|
|
||||||
set_power10_stubs()
|
|
||||||
{
|
{
|
||||||
if (parameters->options().power10_stubs_enum()
|
return (this->power10_relocs_
|
||||||
!= General_options::POWER10_STUBS_NO)
|
&& (parameters->options().power10_stubs_enum()
|
||||||
this->power10_stubs_ = true;
|
!= General_options::POWER10_STUBS_NO));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1106,6 +1108,10 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
plt_localentry0() const
|
plt_localentry0() const
|
||||||
{ return this->plt_localentry0_; }
|
{ return this->plt_localentry0_; }
|
||||||
|
|
||||||
|
bool
|
||||||
|
has_localentry0() const
|
||||||
|
{ return this->has_localentry0_; }
|
||||||
|
|
||||||
void
|
void
|
||||||
set_has_localentry0()
|
set_has_localentry0()
|
||||||
{
|
{
|
||||||
@ -1705,7 +1711,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
Branches branch_info_;
|
Branches branch_info_;
|
||||||
Tocsave_loc tocsave_loc_;
|
Tocsave_loc tocsave_loc_;
|
||||||
|
|
||||||
bool power10_stubs_;
|
bool power10_relocs_;
|
||||||
bool plt_thread_safe_;
|
bool plt_thread_safe_;
|
||||||
bool plt_localentry0_;
|
bool plt_localentry0_;
|
||||||
bool plt_localentry0_init_;
|
bool plt_localentry0_init_;
|
||||||
@ -4190,6 +4196,7 @@ static const uint32_t cmpwi_11_0 = 0x2c0b0000;
|
|||||||
static const uint32_t cror_15_15_15 = 0x4def7b82;
|
static const uint32_t cror_15_15_15 = 0x4def7b82;
|
||||||
static const uint32_t cror_31_31_31 = 0x4ffffb82;
|
static const uint32_t cror_31_31_31 = 0x4ffffb82;
|
||||||
static const uint32_t ld_0_1 = 0xe8010000;
|
static const uint32_t ld_0_1 = 0xe8010000;
|
||||||
|
static const uint32_t ld_0_11 = 0xe80b0000;
|
||||||
static const uint32_t ld_0_12 = 0xe80c0000;
|
static const uint32_t ld_0_12 = 0xe80c0000;
|
||||||
static const uint32_t ld_2_1 = 0xe8410000;
|
static const uint32_t ld_2_1 = 0xe8410000;
|
||||||
static const uint32_t ld_2_2 = 0xe8420000;
|
static const uint32_t ld_2_2 = 0xe8420000;
|
||||||
@ -4572,9 +4579,9 @@ static const unsigned char glink_eh_frame_fde_64v1[] =
|
|||||||
0, 0, 0, 0, // Replaced with offset to .glink.
|
0, 0, 0, 0, // Replaced with offset to .glink.
|
||||||
0, 0, 0, 0, // Replaced with size of .glink.
|
0, 0, 0, 0, // Replaced with size of .glink.
|
||||||
0, // Augmentation size.
|
0, // Augmentation size.
|
||||||
elfcpp::DW_CFA_advance_loc + 1,
|
elfcpp::DW_CFA_advance_loc + 2,
|
||||||
elfcpp::DW_CFA_register, 65, 12,
|
elfcpp::DW_CFA_register, 65, 12,
|
||||||
elfcpp::DW_CFA_advance_loc + 5,
|
elfcpp::DW_CFA_advance_loc + 4,
|
||||||
elfcpp::DW_CFA_restore_extended, 65
|
elfcpp::DW_CFA_restore_extended, 65
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4584,9 +4591,20 @@ static const unsigned char glink_eh_frame_fde_64v2[] =
|
|||||||
0, 0, 0, 0, // Replaced with offset to .glink.
|
0, 0, 0, 0, // Replaced with offset to .glink.
|
||||||
0, 0, 0, 0, // Replaced with size of .glink.
|
0, 0, 0, 0, // Replaced with size of .glink.
|
||||||
0, // Augmentation size.
|
0, // Augmentation size.
|
||||||
elfcpp::DW_CFA_advance_loc + 1,
|
elfcpp::DW_CFA_advance_loc + 2,
|
||||||
elfcpp::DW_CFA_register, 65, 0,
|
elfcpp::DW_CFA_register, 65, 0,
|
||||||
elfcpp::DW_CFA_advance_loc + 7,
|
elfcpp::DW_CFA_advance_loc + 2,
|
||||||
|
elfcpp::DW_CFA_restore_extended, 65
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char glink_eh_frame_fde_64v2_localentry0[] =
|
||||||
|
{
|
||||||
|
0, 0, 0, 0, // Replaced with offset to .glink.
|
||||||
|
0, 0, 0, 0, // Replaced with size of .glink.
|
||||||
|
0, // Augmentation size.
|
||||||
|
elfcpp::DW_CFA_advance_loc + 3,
|
||||||
|
elfcpp::DW_CFA_register, 65, 0,
|
||||||
|
elfcpp::DW_CFA_advance_loc + 2,
|
||||||
elfcpp::DW_CFA_restore_extended, 65
|
elfcpp::DW_CFA_restore_extended, 65
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5525,7 +5543,8 @@ class Output_data_glink : public Output_section_data
|
|||||||
{
|
{
|
||||||
if (size == 64)
|
if (size == 64)
|
||||||
return (8
|
return (8
|
||||||
+ (this->targ_->abiversion() < 2 ? 11 * 4 : 14 * 4));
|
+ (this->targ_->abiversion() < 2 ? 11 * 4
|
||||||
|
: this->targ_->has_localentry0() ? 14 * 4 : 13 * 4));
|
||||||
return 16 * 4;
|
return 16 * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5568,6 +5587,12 @@ Output_data_glink<size, big_endian>::add_eh_frame(Layout* layout)
|
|||||||
sizeof (Eh_cie<64>::eh_frame_cie),
|
sizeof (Eh_cie<64>::eh_frame_cie),
|
||||||
glink_eh_frame_fde_64v1,
|
glink_eh_frame_fde_64v1,
|
||||||
sizeof (glink_eh_frame_fde_64v1));
|
sizeof (glink_eh_frame_fde_64v1));
|
||||||
|
else if (this->targ_->has_localentry0())
|
||||||
|
layout->add_eh_frame_for_plt(this,
|
||||||
|
Eh_cie<64>::eh_frame_cie,
|
||||||
|
sizeof (Eh_cie<64>::eh_frame_cie),
|
||||||
|
glink_eh_frame_fde_64v2_localentry0,
|
||||||
|
sizeof (glink_eh_frame_fde_64v2));
|
||||||
else
|
else
|
||||||
layout->add_eh_frame_for_plt(this,
|
layout->add_eh_frame_for_plt(this,
|
||||||
Eh_cie<64>::eh_frame_cie,
|
Eh_cie<64>::eh_frame_cie,
|
||||||
@ -6798,15 +6823,25 @@ Output_data_glink<size, big_endian>::do_write(Output_file* of)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (this->targ_->has_localentry0())
|
||||||
|
{
|
||||||
|
write_insn<big_endian>(p, std_2_1 + 24), p += 4;
|
||||||
|
}
|
||||||
write_insn<big_endian>(p, mflr_0), p += 4;
|
write_insn<big_endian>(p, mflr_0), p += 4;
|
||||||
write_insn<big_endian>(p, bcl_20_31), p += 4;
|
write_insn<big_endian>(p, bcl_20_31), p += 4;
|
||||||
write_insn<big_endian>(p, mflr_11), p += 4;
|
write_insn<big_endian>(p, mflr_11), p += 4;
|
||||||
write_insn<big_endian>(p, std_2_1 + 24), p += 4;
|
|
||||||
write_insn<big_endian>(p, ld_2_11 + l(-16)), p += 4;
|
|
||||||
write_insn<big_endian>(p, mtlr_0), p += 4;
|
write_insn<big_endian>(p, mtlr_0), p += 4;
|
||||||
|
if (this->targ_->has_localentry0())
|
||||||
|
{
|
||||||
|
write_insn<big_endian>(p, ld_0_11 + l(-20)), p += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_insn<big_endian>(p, ld_0_11 + l(-16)), p += 4;
|
||||||
|
}
|
||||||
write_insn<big_endian>(p, sub_12_12_11), p += 4;
|
write_insn<big_endian>(p, sub_12_12_11), p += 4;
|
||||||
write_insn<big_endian>(p, add_11_2_11), p += 4;
|
write_insn<big_endian>(p, add_11_0_11), p += 4;
|
||||||
write_insn<big_endian>(p, addi_0_12 + l(-48)), p += 4;
|
write_insn<big_endian>(p, addi_0_12 + l(-44)), p += 4;
|
||||||
write_insn<big_endian>(p, ld_12_11 + 0), p += 4;
|
write_insn<big_endian>(p, ld_12_11 + 0), p += 4;
|
||||||
write_insn<big_endian>(p, srdi_0_0_2), p += 4;
|
write_insn<big_endian>(p, srdi_0_0_2), p += 4;
|
||||||
write_insn<big_endian>(p, mtctr_12), p += 4;
|
write_insn<big_endian>(p, mtctr_12), p += 4;
|
||||||
@ -8451,7 +8486,7 @@ Target_powerpc<size, big_endian>::Scan::local(
|
|||||||
case elfcpp::R_PPC64_GOT_TLSLD_PCREL34:
|
case elfcpp::R_PPC64_GOT_TLSLD_PCREL34:
|
||||||
case elfcpp::R_PPC64_GOT_DTPREL_PCREL34:
|
case elfcpp::R_PPC64_GOT_DTPREL_PCREL34:
|
||||||
case elfcpp::R_PPC64_GOT_TPREL_PCREL34:
|
case elfcpp::R_PPC64_GOT_TPREL_PCREL34:
|
||||||
target->set_power10_stubs();
|
target->set_power10_relocs();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -9248,7 +9283,7 @@ Target_powerpc<size, big_endian>::Scan::global(
|
|||||||
case elfcpp::R_PPC64_GOT_TLSLD_PCREL34:
|
case elfcpp::R_PPC64_GOT_TLSLD_PCREL34:
|
||||||
case elfcpp::R_PPC64_GOT_DTPREL_PCREL34:
|
case elfcpp::R_PPC64_GOT_DTPREL_PCREL34:
|
||||||
case elfcpp::R_PPC64_GOT_TPREL_PCREL34:
|
case elfcpp::R_PPC64_GOT_TPREL_PCREL34:
|
||||||
target->set_power10_stubs();
|
target->set_power10_relocs();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -9590,6 +9625,13 @@ Target_powerpc<size, big_endian>::scan_relocs(
|
|||||||
needs_special_offset_handling,
|
needs_special_offset_handling,
|
||||||
local_symbol_count,
|
local_symbol_count,
|
||||||
plocal_symbols);
|
plocal_symbols);
|
||||||
|
|
||||||
|
if (this->plt_localentry0_ && this->power10_relocs_)
|
||||||
|
{
|
||||||
|
gold_warning(_("--plt-localentry is incompatible with "
|
||||||
|
"power10 pc-relative code"));
|
||||||
|
this->plt_localentry0_ = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functor class for processing the global symbol table.
|
// Functor class for processing the global symbol table.
|
||||||
|
Loading…
Reference in New Issue
Block a user