mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-22 11:00:01 +08:00
[GOLD] PowerPC64 @notoc in non-power10 code
Gold version of commit 7aba54da42. elfcpp/ * powerpc.h (R_PPC64_REL24_P9NOTOC): Define. gold/ * powerpc.cc (Target_powerpc::maybe_skip_tls_get_addr_call, is_branch_reloc, max_branch_delta): Handle R_PPC64_REL24_P9NOTOC. (Target_powerpc::Branch_info::make_stub): Likewise. (struct Plt_stub_ent): Add p9notoc_, p9off_, tsize_. (struct Branch_stub_ent): Add p9notoc_, p9off_. (Stub_table::add_plt_call_entry): Handle R_PPC64_REL24_P9NOTOC. (Stub_table::add_long_branch_entry): Likewise. (Stub_table::add_eh_frame): Likewise. (Stub_table::plt_call_size): Return aligned size. Adjust callers. Handle p9notoc_ sizing. (Stub_table::do_write): Write out p9notoc_ stubs. (Target_powerpc::Scan::get_reference_flags, local, global): Handle R_PPC64_REL24_P9NOTOC. (Target_powerpc::Relocate::relocate): Likewise.
This commit is contained in:
@ -184,6 +184,7 @@ enum
|
|||||||
R_PPC64_PLTSEQ_NOTOC = 121,
|
R_PPC64_PLTSEQ_NOTOC = 121,
|
||||||
R_PPC64_PLTCALL_NOTOC = 122,
|
R_PPC64_PLTCALL_NOTOC = 122,
|
||||||
R_PPC64_PCREL_OPT = 123,
|
R_PPC64_PCREL_OPT = 123,
|
||||||
|
R_PPC64_REL24_P9NOTOC = 124,
|
||||||
|
|
||||||
R_PPC64_D34 = 128,
|
R_PPC64_D34 = 128,
|
||||||
R_PPC64_D34_LO = 129,
|
R_PPC64_D34_LO = 129,
|
||||||
|
270
gold/powerpc.cc
270
gold/powerpc.cc
@ -1329,6 +1329,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
bool is_tls_call
|
bool is_tls_call
|
||||||
= ((r_type == elfcpp::R_POWERPC_REL24
|
= ((r_type == elfcpp::R_POWERPC_REL24
|
||||||
|| (size == 64 && r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
|| (size == 64 && r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
||||||
|
|| r_type == elfcpp::R_PPC64_REL24_P9NOTOC
|
||||||
|| r_type == elfcpp::R_PPC_PLTREL24
|
|| r_type == elfcpp::R_PPC_PLTREL24
|
||||||
|| is_plt16_reloc<size>(r_type)
|
|| is_plt16_reloc<size>(r_type)
|
||||||
|| r_type == elfcpp::R_PPC64_PLT_PCREL34
|
|| r_type == elfcpp::R_PPC64_PLT_PCREL34
|
||||||
@ -1891,6 +1892,7 @@ is_branch_reloc(unsigned int r_type)
|
|||||||
{
|
{
|
||||||
return (r_type == elfcpp::R_POWERPC_REL24
|
return (r_type == elfcpp::R_POWERPC_REL24
|
||||||
|| (size == 64 && r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
|| (size == 64 && r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
||||||
|
|| r_type == elfcpp::R_PPC64_REL24_P9NOTOC
|
||||||
|| r_type == elfcpp::R_PPC_PLTREL24
|
|| r_type == elfcpp::R_PPC_PLTREL24
|
||||||
|| r_type == elfcpp::R_PPC_LOCAL24PC
|
|| r_type == elfcpp::R_PPC_LOCAL24PC
|
||||||
|| r_type == elfcpp::R_POWERPC_REL14
|
|| r_type == elfcpp::R_POWERPC_REL14
|
||||||
@ -3447,6 +3449,7 @@ max_branch_delta (unsigned int r_type)
|
|||||||
return 1L << 15;
|
return 1L << 15;
|
||||||
if (r_type == elfcpp::R_POWERPC_REL24
|
if (r_type == elfcpp::R_POWERPC_REL24
|
||||||
|| (size == 64 && r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
|| (size == 64 && r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
||||||
|
|| r_type == elfcpp::R_PPC64_REL24_P9NOTOC
|
||||||
|| r_type == elfcpp::R_PPC_PLTREL24
|
|| r_type == elfcpp::R_PPC_PLTREL24
|
||||||
|| r_type == elfcpp::R_PPC_LOCAL24PC)
|
|| r_type == elfcpp::R_PPC_LOCAL24PC)
|
||||||
return 1L << 25;
|
return 1L << 25;
|
||||||
@ -3621,12 +3624,14 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
|
|||||||
}
|
}
|
||||||
unsigned int local_ent = 0;
|
unsigned int local_ent = 0;
|
||||||
if (size == 64
|
if (size == 64
|
||||||
&& this->r_type_ != elfcpp::R_PPC64_REL24_NOTOC)
|
&& this->r_type_ != elfcpp::R_PPC64_REL24_NOTOC
|
||||||
|
&& this->r_type_ != elfcpp::R_PPC64_REL24_P9NOTOC)
|
||||||
local_ent = elfcpp::ppc64_decode_local_entry(other);
|
local_ent = elfcpp::ppc64_decode_local_entry(other);
|
||||||
Address delta = to + local_ent - from;
|
Address delta = to + local_ent - from;
|
||||||
if (delta + max_branch_offset >= 2 * max_branch_offset
|
if (delta + max_branch_offset >= 2 * max_branch_offset
|
||||||
|| (size == 64
|
|| (size == 64
|
||||||
&& this->r_type_ == elfcpp::R_PPC64_REL24_NOTOC
|
&& (this->r_type_ == elfcpp::R_PPC64_REL24_NOTOC
|
||||||
|
|| this->r_type_ == elfcpp::R_PPC64_REL24_P9NOTOC)
|
||||||
&& (gsym != NULL
|
&& (gsym != NULL
|
||||||
? this->object_->ppc64_needs_toc(gsym)
|
? this->object_->ppc64_needs_toc(gsym)
|
||||||
: this->object_->ppc64_needs_toc(this->r_sym_))))
|
: this->object_->ppc64_needs_toc(this->r_sym_))))
|
||||||
@ -4777,33 +4782,50 @@ class Stub_table : public Output_relaxed_input_section
|
|||||||
struct Plt_stub_ent
|
struct Plt_stub_ent
|
||||||
{
|
{
|
||||||
Plt_stub_ent(unsigned int off, unsigned int indx)
|
Plt_stub_ent(unsigned int off, unsigned int indx)
|
||||||
: off_(off), indx_(indx), iter_(0), notoc_(0), toc_(0),
|
: off_(off), indx_(indx), tocoff_(0), p9off_(0), tsize_ (0), iter_(0),
|
||||||
r2save_(0), localentry0_(0), tocoff_(0)
|
toc_(0), notoc_(0), p9notoc_(0), r2save_(0), localentry0_(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
unsigned int off_;
|
unsigned int off_;
|
||||||
unsigned int indx_;
|
unsigned int indx_;
|
||||||
unsigned int iter_ : 1;
|
// off_ points at p10 notoc stub, tocoff_ is offset from there to
|
||||||
unsigned int notoc_ : 1;
|
// toc stub, p9off_ is offset to p9notoc stub
|
||||||
unsigned int toc_ : 1;
|
|
||||||
unsigned int r2save_ : 1;
|
|
||||||
unsigned int localentry0_ : 1;
|
|
||||||
unsigned int tocoff_ : 8;
|
unsigned int tocoff_ : 8;
|
||||||
|
unsigned int p9off_ : 8;
|
||||||
|
// The size of the toc stub, used to locate blr on tls_get_addr stub.
|
||||||
|
unsigned int tsize_ : 8;
|
||||||
|
// Stub revision management
|
||||||
|
unsigned int iter_ : 1;
|
||||||
|
// The three types of stubs.
|
||||||
|
unsigned int toc_ : 1;
|
||||||
|
unsigned int notoc_ : 1;
|
||||||
|
unsigned int p9notoc_ : 1;
|
||||||
|
// Each with a possible variant saving r2 first
|
||||||
|
unsigned int r2save_ : 1;
|
||||||
|
// Handy cached info from symbol
|
||||||
|
unsigned int localentry0_ : 1;
|
||||||
};
|
};
|
||||||
struct Branch_stub_ent
|
struct Branch_stub_ent
|
||||||
{
|
{
|
||||||
Branch_stub_ent(unsigned int off, bool notoc, bool save_res)
|
Branch_stub_ent(unsigned int off)
|
||||||
: off_(off), iter_(0), notoc_(notoc), toc_(0), save_res_(save_res),
|
: off_(off), tocoff_(0), p9off_(0), iter_(0), toc_(0), notoc_(0),
|
||||||
other_(0), tocoff_(0)
|
p9notoc_(0), save_res_(0), other_(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
unsigned int off_;
|
unsigned int off_;
|
||||||
unsigned int iter_ : 1;
|
// off_ points at p10 notoc stub, tocoff_ is offset from there to
|
||||||
unsigned int notoc_ : 1;
|
// toc stub, p9off_ is offset to p9notoc stub
|
||||||
unsigned int toc_ : 1;
|
|
||||||
unsigned int save_res_ : 1;
|
|
||||||
unsigned int other_ : 3;
|
|
||||||
unsigned int tocoff_ : 8;
|
unsigned int tocoff_ : 8;
|
||||||
|
unsigned int p9off_ : 8;
|
||||||
|
// Stub revision management
|
||||||
|
unsigned int iter_ : 1;
|
||||||
|
// Four types of stubs.
|
||||||
|
unsigned int toc_ : 1;
|
||||||
|
unsigned int notoc_ : 1;
|
||||||
|
unsigned int p9notoc_ : 1;
|
||||||
|
unsigned int save_res_ : 1;
|
||||||
|
// Handy cached info from symbol
|
||||||
|
unsigned int other_ : 3;
|
||||||
};
|
};
|
||||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
|
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
|
||||||
static const Address invalid_address = static_cast<Address>(0) - 1;
|
static const Address invalid_address = static_cast<Address>(0) - 1;
|
||||||
@ -5223,14 +5245,24 @@ Stub_table<size, big_endian>::add_plt_call_entry(
|
|||||||
p.first->second.localentry0_ = 1;
|
p.first->second.localentry0_ = 1;
|
||||||
this->targ_->set_has_localentry0();
|
this->targ_->set_has_localentry0();
|
||||||
}
|
}
|
||||||
if (r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
if (r_type == elfcpp::R_PPC64_REL24_NOTOC
|
||||||
|
|| r_type == elfcpp::R_PPC64_REL24_P9NOTOC)
|
||||||
{
|
{
|
||||||
if (!p.second && !p.first->second.notoc_
|
if (this->targ_->power10_stubs()
|
||||||
&& (!this->targ_->power10_stubs()
|
&& (!this->targ_->power10_stubs_auto()
|
||||||
|| this->targ_->power10_stubs_auto()))
|
|| r_type == elfcpp::R_PPC64_REL24_NOTOC))
|
||||||
|
{
|
||||||
|
if (!p.second && !p.first->second.notoc_)
|
||||||
this->need_resize_ = true;
|
this->need_resize_ = true;
|
||||||
p.first->second.notoc_ = 1;
|
p.first->second.notoc_ = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!p.second && !p.first->second.p9notoc_)
|
||||||
|
this->need_resize_ = true;
|
||||||
|
p.first->second.p9notoc_ = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!p.second && !p.first->second.toc_)
|
if (!p.second && !p.first->second.toc_)
|
||||||
@ -5254,7 +5286,6 @@ Stub_table<size, big_endian>::add_plt_call_entry(
|
|||||||
this->plt_size_ += this->plt_call_size(p.first);
|
this->plt_size_ += this->plt_call_size(p.first);
|
||||||
if (this->targ_->is_tls_get_addr_opt(gsym))
|
if (this->targ_->is_tls_get_addr_opt(gsym))
|
||||||
this->targ_->set_has_tls_get_addr_opt();
|
this->targ_->set_has_tls_get_addr_opt();
|
||||||
this->plt_size_ = this->plt_call_align(this->plt_size_);
|
|
||||||
}
|
}
|
||||||
return this->can_reach_stub(from, p.first->second.off_, r_type);
|
return this->can_reach_stub(from, p.first->second.off_, r_type);
|
||||||
}
|
}
|
||||||
@ -5281,14 +5312,24 @@ Stub_table<size, big_endian>::add_plt_call_entry(
|
|||||||
p.first->second.localentry0_ = 1;
|
p.first->second.localentry0_ = 1;
|
||||||
this->targ_->set_has_localentry0();
|
this->targ_->set_has_localentry0();
|
||||||
}
|
}
|
||||||
if (r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
if (r_type == elfcpp::R_PPC64_REL24_NOTOC
|
||||||
|
|| r_type == elfcpp::R_PPC64_REL24_P9NOTOC)
|
||||||
{
|
{
|
||||||
if (!p.second && !p.first->second.notoc_
|
if (this->targ_->power10_stubs()
|
||||||
&& (!this->targ_->power10_stubs()
|
&& (!this->targ_->power10_stubs_auto()
|
||||||
|| this->targ_->power10_stubs_auto()))
|
|| r_type == elfcpp::R_PPC64_REL24_NOTOC))
|
||||||
|
{
|
||||||
|
if (!p.second && !p.first->second.notoc_)
|
||||||
this->need_resize_ = true;
|
this->need_resize_ = true;
|
||||||
p.first->second.notoc_ = 1;
|
p.first->second.notoc_ = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!p.second && !p.first->second.p9notoc_)
|
||||||
|
this->need_resize_ = true;
|
||||||
|
p.first->second.p9notoc_ = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!p.second && !p.first->second.toc_)
|
if (!p.second && !p.first->second.toc_)
|
||||||
@ -5310,7 +5351,6 @@ Stub_table<size, big_endian>::add_plt_call_entry(
|
|||||||
p.first->second.off_ = this->plt_size_;
|
p.first->second.off_ = this->plt_size_;
|
||||||
}
|
}
|
||||||
this->plt_size_ += this->plt_call_size(p.first);
|
this->plt_size_ += this->plt_call_size(p.first);
|
||||||
this->plt_size_ = this->plt_call_align(this->plt_size_);
|
|
||||||
}
|
}
|
||||||
return this->can_reach_stub(from, p.first->second.off_, r_type);
|
return this->can_reach_stub(from, p.first->second.off_, r_type);
|
||||||
}
|
}
|
||||||
@ -5384,16 +5424,34 @@ Stub_table<size, big_endian>::add_long_branch_entry(
|
|||||||
bool save_res)
|
bool save_res)
|
||||||
{
|
{
|
||||||
Branch_stub_key key(to);
|
Branch_stub_key key(to);
|
||||||
bool notoc = (size == 64 && r_type == elfcpp::R_PPC64_REL24_NOTOC);
|
Branch_stub_ent ent(this->branch_size_);
|
||||||
Branch_stub_ent ent(this->branch_size_, notoc, save_res);
|
|
||||||
std::pair<typename Branch_stub_entries::iterator, bool> p
|
std::pair<typename Branch_stub_entries::iterator, bool> p
|
||||||
= this->long_branch_stubs_.insert(std::make_pair(key, ent));
|
= this->long_branch_stubs_.insert(std::make_pair(key, ent));
|
||||||
if (notoc)
|
if (save_res)
|
||||||
|
{
|
||||||
|
if (!p.second && !p.first->second.save_res_)
|
||||||
|
this->need_resize_ = true;
|
||||||
|
p.first->second.save_res_ = true;
|
||||||
|
}
|
||||||
|
else if (size == 64
|
||||||
|
&& (r_type == elfcpp::R_PPC64_REL24_NOTOC
|
||||||
|
|| r_type == elfcpp::R_PPC64_REL24_P9NOTOC))
|
||||||
|
{
|
||||||
|
if (this->targ_->power10_stubs()
|
||||||
|
&& (!this->targ_->power10_stubs_auto()
|
||||||
|
|| r_type == elfcpp::R_PPC64_REL24_NOTOC))
|
||||||
{
|
{
|
||||||
if (!p.second && !p.first->second.notoc_)
|
if (!p.second && !p.first->second.notoc_)
|
||||||
this->need_resize_ = true;
|
this->need_resize_ = true;
|
||||||
p.first->second.notoc_ = true;
|
p.first->second.notoc_ = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!p.second && !p.first->second.p9notoc_)
|
||||||
|
this->need_resize_ = true;
|
||||||
|
p.first->second.p9notoc_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!p.second && !p.first->second.toc_)
|
if (!p.second && !p.first->second.toc_)
|
||||||
@ -5402,7 +5460,6 @@ Stub_table<size, big_endian>::add_long_branch_entry(
|
|||||||
}
|
}
|
||||||
if (size == 64 && p.first->second.other_ == 0)
|
if (size == 64 && p.first->second.other_ == 0)
|
||||||
p.first->second.other_ = other;
|
p.first->second.other_ = other;
|
||||||
gold_assert(save_res == p.first->second.save_res_);
|
|
||||||
if (p.second || (this->resizing_ && !p.first->second.iter_))
|
if (p.second || (this->resizing_ && !p.first->second.iter_))
|
||||||
{
|
{
|
||||||
if (this->resizing_)
|
if (this->resizing_)
|
||||||
@ -5500,11 +5557,11 @@ Stub_table<size, big_endian>::add_eh_frame(Layout* layout)
|
|||||||
for (plt_iter cs = this->plt_call_stubs_.begin();
|
for (plt_iter cs = this->plt_call_stubs_.begin();
|
||||||
cs != this->plt_call_stubs_.end();
|
cs != this->plt_call_stubs_.end();
|
||||||
++cs)
|
++cs)
|
||||||
if ((this->targ_->is_tls_get_addr_opt(cs->first.sym_)
|
if (cs->second.p9notoc_
|
||||||
|
|| (cs->second.toc_
|
||||||
&& cs->second.r2save_
|
&& cs->second.r2save_
|
||||||
&& !cs->second.localentry0_)
|
&& !cs->second.localentry0_
|
||||||
|| (cs->second.notoc_
|
&& this->targ_->is_tls_get_addr_opt(cs->first.sym_)))
|
||||||
&& !this->targ_->power10_stubs()))
|
|
||||||
calls.push_back(cs);
|
calls.push_back(cs);
|
||||||
if (calls.size() > 1)
|
if (calls.size() > 1)
|
||||||
std::stable_sort(calls.begin(), calls.end(),
|
std::stable_sort(calls.begin(), calls.end(),
|
||||||
@ -5540,26 +5597,30 @@ Stub_table<size, big_endian>::add_eh_frame(Layout* layout)
|
|||||||
if (this->targ_->is_tls_get_addr_opt(cs->first.sym_))
|
if (this->targ_->is_tls_get_addr_opt(cs->first.sym_))
|
||||||
{
|
{
|
||||||
off += 7 * 4;
|
off += 7 * 4;
|
||||||
if (cs->second.r2save_
|
if (cs->second.toc_
|
||||||
|
&& cs->second.r2save_
|
||||||
&& !cs->second.localentry0_)
|
&& !cs->second.localentry0_)
|
||||||
{
|
{
|
||||||
off += 2 * 4;
|
off += cs->second.tocoff_ + 2 * 4;
|
||||||
eh_advance<big_endian>(fde, off - last_eh_loc);
|
eh_advance<big_endian>(fde, off - last_eh_loc);
|
||||||
fde.resize(fde.size() + 6);
|
fde.resize(fde.size() + 6);
|
||||||
unsigned char* p = &*fde.end() - 6;
|
unsigned char* p = &*fde.end() - 6;
|
||||||
*p++ = elfcpp::DW_CFA_offset_extended_sf;
|
*p++ = elfcpp::DW_CFA_offset_extended_sf;
|
||||||
*p++ = 65;
|
*p++ = 65;
|
||||||
*p++ = -(this->targ_->stk_linker() / 8) & 0x7f;
|
*p++ = -(this->targ_->stk_linker() / 8) & 0x7f;
|
||||||
unsigned int delta = this->plt_call_size(cs) - 4 - 9 * 4;
|
unsigned int delta = cs->second.tsize_ - 9 * 4 - 4;
|
||||||
*p++ = elfcpp::DW_CFA_advance_loc + delta / 4;
|
*p++ = elfcpp::DW_CFA_advance_loc + delta / 4;
|
||||||
*p++ = elfcpp::DW_CFA_restore_extended;
|
*p++ = elfcpp::DW_CFA_restore_extended;
|
||||||
*p++ = 65;
|
*p++ = 65;
|
||||||
last_eh_loc = off + delta;
|
last_eh_loc = off + delta;
|
||||||
continue;
|
off = cs->second.off_ + 7 * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// notoc stubs also should describe LR changes, to support
|
// notoc stubs also should describe LR changes, to support
|
||||||
// asynchronous exceptions.
|
// asynchronous exceptions.
|
||||||
|
if (cs->second.p9notoc_)
|
||||||
|
{
|
||||||
|
off += cs->second.p9off_;
|
||||||
off += (cs->second.r2save_ ? 4 : 0) + 8;
|
off += (cs->second.r2save_ ? 4 : 0) + 8;
|
||||||
eh_advance<big_endian>(fde, off - last_eh_loc);
|
eh_advance<big_endian>(fde, off - last_eh_loc);
|
||||||
fde.resize(fde.size() + 6);
|
fde.resize(fde.size() + 6);
|
||||||
@ -5572,6 +5633,7 @@ Stub_table<size, big_endian>::add_eh_frame(Layout* layout)
|
|||||||
*p++ = 65;
|
*p++ = 65;
|
||||||
last_eh_loc = off + 8;
|
last_eh_loc = off + 8;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < branches.size(); i++)
|
for (unsigned int i = 0; i < branches.size(); i++)
|
||||||
{
|
{
|
||||||
@ -5842,7 +5904,7 @@ Stub_table<size, big_endian>::define_stub_syms(Symbol_table* symtab)
|
|||||||
sprintf(name, "%08x.plt_call.%s%s%s", this->uniq_, obj, symname, add);
|
sprintf(name, "%08x.plt_call.%s%s%s", this->uniq_, obj, symname, add);
|
||||||
Address value
|
Address value
|
||||||
= this->stub_address() - this->address() + cs->second.off_;
|
= this->stub_address() - this->address() + cs->second.off_;
|
||||||
unsigned int stub_size = this->plt_call_align(this->plt_call_size(cs));
|
unsigned int stub_size = this->plt_call_size(cs);
|
||||||
this->targ_->define_local(symtab, name, this, value, stub_size);
|
this->targ_->define_local(symtab, name, this, value, stub_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6108,9 +6170,10 @@ Stub_table<size, big_endian>::plt_call_size(
|
|||||||
{
|
{
|
||||||
if (size == 32)
|
if (size == 32)
|
||||||
{
|
{
|
||||||
const Symbol* gsym = p->first.sym_;
|
unsigned int bytes = 4 * 4;
|
||||||
return (4 * 4
|
if (this->targ_->is_tls_get_addr_opt(p->first.sym_))
|
||||||
+ (this->targ_->is_tls_get_addr_opt(gsym) ? 8 * 4 : 0));
|
bytes = 12 * 4;
|
||||||
|
return this->plt_call_align(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Output_data_plt_powerpc<size, big_endian>* plt;
|
const Output_data_plt_powerpc<size, big_endian>* plt;
|
||||||
@ -6135,7 +6198,6 @@ Stub_table<size, big_endian>::plt_call_size(
|
|||||||
bytes += 8 * 4;
|
bytes += 8 * 4;
|
||||||
bytes = this->plt_call_align(bytes);
|
bytes = this->plt_call_align(bytes);
|
||||||
}
|
}
|
||||||
unsigned int tail = 0;
|
|
||||||
if (p->second.toc_)
|
if (p->second.toc_)
|
||||||
{
|
{
|
||||||
p->second.tocoff_ = bytes;
|
p->second.tocoff_ = bytes;
|
||||||
@ -6143,18 +6205,43 @@ Stub_table<size, big_endian>::plt_call_size(
|
|||||||
{
|
{
|
||||||
bytes += 7 * 4;
|
bytes += 7 * 4;
|
||||||
if (p->second.r2save_ && !p->second.localentry0_)
|
if (p->second.r2save_ && !p->second.localentry0_)
|
||||||
{
|
bytes += 2 * 4 + 4 * 4;
|
||||||
bytes += 2 * 4;
|
|
||||||
tail = 4 * 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (p->second.r2save_)
|
if (p->second.r2save_)
|
||||||
bytes += 4;
|
bytes += 4;
|
||||||
uint64_t got_addr = this->targ_->toc_pointer();
|
uint64_t got_addr = this->targ_->toc_pointer();
|
||||||
uint64_t off = plt_addr - got_addr;
|
uint64_t off = plt_addr - got_addr;
|
||||||
bytes += 3 * 4 + 4 * (ha(off) != 0);
|
bytes += 3 * 4 + 4 * (ha(off) != 0);
|
||||||
|
p->second.tsize_ = bytes - p->second.tocoff_;
|
||||||
|
bytes = this->plt_call_align(bytes);
|
||||||
}
|
}
|
||||||
return bytes + tail;
|
if (p->second.p9notoc_)
|
||||||
|
{
|
||||||
|
p->second.p9off_ = bytes;
|
||||||
|
if (this->targ_->is_tls_get_addr_opt(p->first.sym_))
|
||||||
|
bytes += 7 * 4;
|
||||||
|
uint64_t from = this->stub_address() + p->second.off_ + bytes + 2 * 4;
|
||||||
|
uint64_t off = plt_addr - from;
|
||||||
|
if (off + 0x8000 < 0x10000)
|
||||||
|
bytes += 7 * 4;
|
||||||
|
else if (off + 0x80008000ULL < 0x100000000ULL)
|
||||||
|
bytes += 8 * 4;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bytes += 8 * 4;
|
||||||
|
if (off + 0x800000000000ULL >= 0x1000000000000ULL
|
||||||
|
&& ((off >> 32) & 0xffff) != 0)
|
||||||
|
bytes += 4;
|
||||||
|
if (((off >> 32) & 0xffffffffULL) != 0)
|
||||||
|
bytes += 4;
|
||||||
|
if (hi(off) != 0)
|
||||||
|
bytes += 4;
|
||||||
|
if (l(off) != 0)
|
||||||
|
bytes += 4;
|
||||||
|
}
|
||||||
|
bytes = this->plt_call_align(bytes);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -6184,10 +6271,10 @@ Stub_table<size, big_endian>::plt_call_size(
|
|||||||
bytes += 7 * 4;
|
bytes += 7 * 4;
|
||||||
else
|
else
|
||||||
bytes += 8 * 4;
|
bytes += 8 * 4;
|
||||||
return bytes + tail;
|
return this->plt_call_align(bytes + tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->second.notoc_)
|
if (p->second.p9notoc_)
|
||||||
{
|
{
|
||||||
uint64_t from = this->stub_address() + p->second.off_ + bytes + 2 * 4;
|
uint64_t from = this->stub_address() + p->second.off_ + bytes + 2 * 4;
|
||||||
uint64_t off = plt_addr - from;
|
uint64_t off = plt_addr - from;
|
||||||
@ -6208,7 +6295,7 @@ Stub_table<size, big_endian>::plt_call_size(
|
|||||||
if (l(off) != 0)
|
if (l(off) != 0)
|
||||||
bytes += 4;
|
bytes += 4;
|
||||||
}
|
}
|
||||||
return bytes + tail;
|
return this->plt_call_align(bytes + tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t got_addr = this->targ_->toc_pointer();
|
uint64_t got_addr = this->targ_->toc_pointer();
|
||||||
@ -6223,7 +6310,7 @@ Stub_table<size, big_endian>::plt_call_size(
|
|||||||
+ 8 * thread_safe
|
+ 8 * thread_safe
|
||||||
+ 4 * (ha(off + 8 + 8 * static_chain) != ha(off)));
|
+ 4 * (ha(off + 8 + 8 * static_chain) != ha(off)));
|
||||||
}
|
}
|
||||||
return bytes + tail;
|
return this->plt_call_align(bytes + tail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6400,6 +6487,19 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
|
|||||||
else
|
else
|
||||||
write_insn<big_endian>(p, bctr);
|
write_insn<big_endian>(p, bctr);
|
||||||
}
|
}
|
||||||
|
if (cs->second.p9notoc_)
|
||||||
|
{
|
||||||
|
if (this->targ_->is_tls_get_addr_opt(cs->first.sym_))
|
||||||
|
this->build_tls_opt_head(&p, false);
|
||||||
|
Address from = this->stub_address() + (p - oview);
|
||||||
|
Address delta = plt_addr - from;
|
||||||
|
p = build_notoc_offset<big_endian>(p, delta, true);
|
||||||
|
write_insn<big_endian>(p, mtctr_12);
|
||||||
|
p += 4;
|
||||||
|
write_insn<big_endian>(p, bctr);
|
||||||
|
p += 4;
|
||||||
|
p = oview + this->plt_call_align(p - oview);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -6494,6 +6594,23 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
|
|||||||
write_insn<big_endian>(p, bctr);
|
write_insn<big_endian>(p, bctr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (bs->second.p9notoc_)
|
||||||
|
{
|
||||||
|
unsigned char* startp = p;
|
||||||
|
p = build_notoc_offset<big_endian>(p, delta, false);
|
||||||
|
delta -= p - startp;
|
||||||
|
startp = p;
|
||||||
|
if (delta + (1 << 25) < 2 << 25)
|
||||||
|
write_insn<big_endian>(p, b | (delta & 0x3fffffc));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_insn<big_endian>(p, mtctr_12);
|
||||||
|
p += 4;
|
||||||
|
write_insn<big_endian>(p, bctr);
|
||||||
|
}
|
||||||
|
p += 4;
|
||||||
|
delta -= p - startp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -6544,7 +6661,7 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
|
|||||||
write_insn<big_endian>(p, std_2_1 + this->targ_->stk_toc());
|
write_insn<big_endian>(p, std_2_1 + this->targ_->stk_toc());
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
if (cs->second.notoc_)
|
if (cs->second.p9notoc_)
|
||||||
{
|
{
|
||||||
Address from = this->stub_address() + (p - oview) + 8;
|
Address from = this->stub_address() + (p - oview) + 8;
|
||||||
Address off = plt_addr - from;
|
Address off = plt_addr - from;
|
||||||
@ -6722,9 +6839,9 @@ Stub_table<size, big_endian>::do_write(Output_file* of)
|
|||||||
p = oview + off;
|
p = oview + off;
|
||||||
Address loc = this->stub_address() + off;
|
Address loc = this->stub_address() + off;
|
||||||
Address delta = bs->first.dest_ - loc;
|
Address delta = bs->first.dest_ - loc;
|
||||||
if (!bs->second.notoc_)
|
if (!bs->second.p9notoc_)
|
||||||
delta += elfcpp::ppc64_decode_local_entry(bs->second.other_);
|
delta += elfcpp::ppc64_decode_local_entry(bs->second.other_);
|
||||||
if (bs->second.notoc_)
|
if (bs->second.p9notoc_)
|
||||||
{
|
{
|
||||||
unsigned char* startp = p;
|
unsigned char* startp = p;
|
||||||
p = build_notoc_offset<big_endian>(p, off, false);
|
p = build_notoc_offset<big_endian>(p, off, false);
|
||||||
@ -7619,6 +7736,7 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(
|
|||||||
if (size == 32)
|
if (size == 32)
|
||||||
break;
|
break;
|
||||||
// Fall through.
|
// Fall through.
|
||||||
|
case elfcpp::R_PPC64_REL24_P9NOTOC:
|
||||||
case elfcpp::R_POWERPC_REL24:
|
case elfcpp::R_POWERPC_REL24:
|
||||||
case elfcpp::R_PPC_PLTREL24:
|
case elfcpp::R_PPC_PLTREL24:
|
||||||
case elfcpp::R_POWERPC_REL14:
|
case elfcpp::R_POWERPC_REL14:
|
||||||
@ -7861,6 +7979,7 @@ Target_powerpc<size, big_endian>::Scan::reloc_needs_plt_for_ifunc(
|
|||||||
if (size == 32)
|
if (size == 32)
|
||||||
break;
|
break;
|
||||||
// Fall through.
|
// Fall through.
|
||||||
|
case elfcpp::R_PPC64_REL24_P9NOTOC:
|
||||||
case elfcpp::R_POWERPC_ADDR24:
|
case elfcpp::R_POWERPC_ADDR24:
|
||||||
case elfcpp::R_POWERPC_ADDR14:
|
case elfcpp::R_POWERPC_ADDR14:
|
||||||
case elfcpp::R_POWERPC_ADDR14_BRTAKEN:
|
case elfcpp::R_POWERPC_ADDR14_BRTAKEN:
|
||||||
@ -8124,6 +8243,7 @@ Target_powerpc<size, big_endian>::Scan::local(
|
|||||||
if (size == 32)
|
if (size == 32)
|
||||||
break;
|
break;
|
||||||
// Fall through.
|
// Fall through.
|
||||||
|
case elfcpp::R_PPC64_REL24_P9NOTOC:
|
||||||
case elfcpp::R_POWERPC_REL24:
|
case elfcpp::R_POWERPC_REL24:
|
||||||
case elfcpp::R_PPC_PLTREL24:
|
case elfcpp::R_PPC_PLTREL24:
|
||||||
case elfcpp::R_PPC_LOCAL24PC:
|
case elfcpp::R_PPC_LOCAL24PC:
|
||||||
@ -8873,6 +8993,7 @@ Target_powerpc<size, big_endian>::Scan::global(
|
|||||||
if (size == 32)
|
if (size == 32)
|
||||||
break;
|
break;
|
||||||
// Fall through.
|
// Fall through.
|
||||||
|
case elfcpp::R_PPC64_REL24_P9NOTOC:
|
||||||
case elfcpp::R_PPC_PLTREL24:
|
case elfcpp::R_PPC_PLTREL24:
|
||||||
case elfcpp::R_POWERPC_REL24:
|
case elfcpp::R_POWERPC_REL24:
|
||||||
if (!is_ifunc)
|
if (!is_ifunc)
|
||||||
@ -10630,15 +10751,25 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
|
const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
|
||||||
elfcpp::Shdr<size, big_endian> shdr(relinfo->reloc_shdr);
|
elfcpp::Shdr<size, big_endian> shdr(relinfo->reloc_shdr);
|
||||||
size_t reloc_count = shdr.get_sh_size() / reloc_size;
|
size_t reloc_count = shdr.get_sh_size() / reloc_size;
|
||||||
if (size == 64
|
if (size == 64)
|
||||||
&& r_type != elfcpp::R_PPC64_REL24_NOTOC)
|
{
|
||||||
|
if (r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
||||||
|
{
|
||||||
|
if (!ent->notoc_)
|
||||||
|
value += ent->p9off_;
|
||||||
|
}
|
||||||
|
else if (r_type == elfcpp::R_PPC64_REL24_P9NOTOC)
|
||||||
|
value += ent->p9off_;
|
||||||
|
else
|
||||||
value += ent->tocoff_;
|
value += ent->tocoff_;
|
||||||
|
}
|
||||||
if (size == 64
|
if (size == 64
|
||||||
&& ent->r2save_
|
&& ent->r2save_
|
||||||
&& !(gsym != NULL
|
&& !(gsym != NULL
|
||||||
&& target->is_tls_get_addr_opt(gsym)))
|
&& target->is_tls_get_addr_opt(gsym)))
|
||||||
{
|
{
|
||||||
if (r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
if (r_type == elfcpp::R_PPC64_REL24_NOTOC
|
||||||
|
|| r_type == elfcpp::R_PPC64_REL24_P9NOTOC)
|
||||||
{
|
{
|
||||||
if (!(target->power10_stubs()
|
if (!(target->power10_stubs()
|
||||||
&& target->power10_stubs_auto()))
|
&& target->power10_stubs_auto()))
|
||||||
@ -11078,6 +11209,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
unsigned int r_type2
|
unsigned int r_type2
|
||||||
= elfcpp::elf_r_type<size>(next_rela.get_r_info());
|
= elfcpp::elf_r_type<size>(next_rela.get_r_info());
|
||||||
if ((r_type2 == elfcpp::R_PPC64_REL24_NOTOC
|
if ((r_type2 == elfcpp::R_PPC64_REL24_NOTOC
|
||||||
|
|| r_type2 == elfcpp::R_PPC64_REL24_P9NOTOC
|
||||||
|| r_type2 == elfcpp::R_PPC64_PLTCALL_NOTOC)
|
|| r_type2 == elfcpp::R_PPC64_PLTCALL_NOTOC)
|
||||||
&& next_rela.get_r_offset() == rela.get_r_offset())
|
&& next_rela.get_r_offset() == rela.get_r_offset())
|
||||||
is_pcrel = true;
|
is_pcrel = true;
|
||||||
@ -11118,6 +11250,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
unsigned int r_type2
|
unsigned int r_type2
|
||||||
= elfcpp::elf_r_type<size>(next_rela.get_r_info());
|
= elfcpp::elf_r_type<size>(next_rela.get_r_info());
|
||||||
if ((r_type2 == elfcpp::R_PPC64_REL24_NOTOC
|
if ((r_type2 == elfcpp::R_PPC64_REL24_NOTOC
|
||||||
|
|| r_type2 == elfcpp::R_PPC64_REL24_P9NOTOC
|
||||||
|| r_type2 == elfcpp::R_PPC64_PLTCALL_NOTOC)
|
|| r_type2 == elfcpp::R_PPC64_PLTCALL_NOTOC)
|
||||||
&& next_rela.get_r_offset() == rela.get_r_offset())
|
&& next_rela.get_r_offset() == rela.get_r_offset())
|
||||||
is_pcrel = true;
|
is_pcrel = true;
|
||||||
@ -11227,7 +11360,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
if (max_branch != 0
|
if (max_branch != 0
|
||||||
&& (value + local_ent - address + max_branch >= 2 * max_branch
|
&& (value + local_ent - address + max_branch >= 2 * max_branch
|
||||||
|| (size == 64
|
|| (size == 64
|
||||||
&& r_type == elfcpp::R_PPC64_REL24_NOTOC
|
&& (r_type == elfcpp::R_PPC64_REL24_NOTOC
|
||||||
|
|| r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
||||||
&& (gsym != NULL
|
&& (gsym != NULL
|
||||||
? object->ppc64_needs_toc(gsym)
|
? object->ppc64_needs_toc(gsym)
|
||||||
: object->ppc64_needs_toc(r_sym)))))
|
: object->ppc64_needs_toc(r_sym)))))
|
||||||
@ -11250,10 +11384,19 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
value = (stub_table->stub_address()
|
value = (stub_table->stub_address()
|
||||||
+ stub_table->plt_size()
|
+ stub_table->plt_size()
|
||||||
+ ent->off_);
|
+ ent->off_);
|
||||||
if (size == 64
|
if (size == 64)
|
||||||
&& r_type != elfcpp::R_PPC64_REL24_NOTOC)
|
{
|
||||||
|
if (r_type == elfcpp::R_PPC64_REL24_NOTOC)
|
||||||
|
{
|
||||||
|
if (!ent->notoc_)
|
||||||
|
value += ent->p9off_;
|
||||||
|
}
|
||||||
|
else if (r_type == elfcpp::R_PPC64_REL24_P9NOTOC)
|
||||||
|
value += ent->p9off_;
|
||||||
|
else
|
||||||
value += ent->tocoff_;
|
value += ent->tocoff_;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
has_stub_value = true;
|
has_stub_value = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11268,6 +11411,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
if (size == 32)
|
if (size == 32)
|
||||||
break;
|
break;
|
||||||
// Fall through.
|
// Fall through.
|
||||||
|
case elfcpp::R_PPC64_REL24_P9NOTOC:
|
||||||
case elfcpp::R_PPC64_REL64:
|
case elfcpp::R_PPC64_REL64:
|
||||||
case elfcpp::R_POWERPC_REL32:
|
case elfcpp::R_POWERPC_REL32:
|
||||||
case elfcpp::R_POWERPC_REL24:
|
case elfcpp::R_POWERPC_REL24:
|
||||||
@ -11802,6 +11946,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
if (size == 32)
|
if (size == 32)
|
||||||
break;
|
break;
|
||||||
// Fall through.
|
// Fall through.
|
||||||
|
case elfcpp::R_PPC64_REL24_P9NOTOC:
|
||||||
case elfcpp::R_POWERPC_ADDR24:
|
case elfcpp::R_POWERPC_ADDR24:
|
||||||
case elfcpp::R_POWERPC_ADDR14:
|
case elfcpp::R_POWERPC_ADDR14:
|
||||||
case elfcpp::R_POWERPC_ADDR14_BRTAKEN:
|
case elfcpp::R_POWERPC_ADDR14_BRTAKEN:
|
||||||
@ -11905,6 +12050,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
|||||||
if (size == 32)
|
if (size == 32)
|
||||||
goto unsupp; // R_PPC_EMB_RELSDA
|
goto unsupp; // R_PPC_EMB_RELSDA
|
||||||
// Fall through.
|
// Fall through.
|
||||||
|
case elfcpp::R_PPC64_REL24_P9NOTOC:
|
||||||
case elfcpp::R_POWERPC_ADDR24:
|
case elfcpp::R_POWERPC_ADDR24:
|
||||||
case elfcpp::R_POWERPC_REL24:
|
case elfcpp::R_POWERPC_REL24:
|
||||||
case elfcpp::R_PPC_PLTREL24:
|
case elfcpp::R_PPC_PLTREL24:
|
||||||
|
Reference in New Issue
Block a user