* target-reloc.h (scan_relocs): Call scan.local for relocs
against symbols in discarded sections. Pass is_discarded param. * arm.cc, * i386.cc, * sparc.cc, * x86_64.cc (Target_*::Scan::local): Add is_discarded param. * powerpc (Target_powerpc::Scan::local): Likewise. Use is_discarded to flag opd entry as discarded. Don't emit dyn relocs on such entries. (Target_powerpc::Scan::global): Similarly detect and handle such opd entries. (Powerpc_relobj): Replace opd_ent_shndx_ and opd_ent_off_ with opd_ent_. Update all uses. (Powerpc_relobj::get_opd_discard, set_opd_discard): New functions. (Target_powerpc::relocate_section): Zero out discarded opd entry relocs.
This commit is contained in:
parent
7c0e90d28c
commit
bfdfa4cd8d
7 changed files with 209 additions and 78 deletions
|
@ -1,3 +1,21 @@
|
||||||
|
2012-09-13 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* target-reloc.h (scan_relocs): Call scan.local for relocs
|
||||||
|
against symbols in discarded sections. Pass is_discarded
|
||||||
|
param.
|
||||||
|
* arm.cc, * i386.cc, * sparc.cc, * x86_64.cc (Target_*::Scan::local):
|
||||||
|
Add is_discarded param.
|
||||||
|
* powerpc (Target_powerpc::Scan::local): Likewise. Use
|
||||||
|
is_discarded to flag opd entry as discarded. Don't emit dyn
|
||||||
|
relocs on such entries.
|
||||||
|
(Target_powerpc::Scan::global): Similarly detect and handle
|
||||||
|
such opd entries.
|
||||||
|
(Powerpc_relobj): Replace opd_ent_shndx_ and opd_ent_off_ with
|
||||||
|
opd_ent_. Update all uses.
|
||||||
|
(Powerpc_relobj::get_opd_discard, set_opd_discard): New functions.
|
||||||
|
(Target_powerpc::relocate_section): Zero out discarded opd
|
||||||
|
entry relocs.
|
||||||
|
|
||||||
2012-09-12 Ian Lance Taylor <iant@google.com>
|
2012-09-12 Ian Lance Taylor <iant@google.com>
|
||||||
|
|
||||||
PR gold/14570
|
PR gold/14570
|
||||||
|
|
|
@ -2551,7 +2551,8 @@ class Target_arm : public Sized_target<32, big_endian>
|
||||||
unsigned int data_shndx,
|
unsigned int data_shndx,
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rel<32, big_endian>& reloc, unsigned int r_type,
|
const elfcpp::Rel<32, big_endian>& reloc, unsigned int r_type,
|
||||||
const elfcpp::Sym<32, big_endian>& lsym);
|
const elfcpp::Sym<32, big_endian>& lsym,
|
||||||
|
bool is_discarded);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
global(Symbol_table* symtab, Layout* layout, Target_arm* target,
|
global(Symbol_table* symtab, Layout* layout, Target_arm* target,
|
||||||
|
@ -7857,8 +7858,12 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rel<32, big_endian>& reloc,
|
const elfcpp::Rel<32, big_endian>& reloc,
|
||||||
unsigned int r_type,
|
unsigned int r_type,
|
||||||
const elfcpp::Sym<32, big_endian>& lsym)
|
const elfcpp::Sym<32, big_endian>& lsym,
|
||||||
|
bool is_discarded)
|
||||||
{
|
{
|
||||||
|
if (is_discarded)
|
||||||
|
return;
|
||||||
|
|
||||||
r_type = get_real_reloc_type(r_type);
|
r_type = get_real_reloc_type(r_type);
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
|
|
23
gold/i386.cc
23
gold/i386.cc
|
@ -538,7 +538,8 @@ class Target_i386 : public Sized_target<32, false>
|
||||||
unsigned int data_shndx,
|
unsigned int data_shndx,
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
|
const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
|
||||||
const elfcpp::Sym<32, false>& lsym);
|
const elfcpp::Sym<32, false>& lsym,
|
||||||
|
bool is_discarded);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
global(Symbol_table* symtab, Layout* layout, Target_i386* target,
|
global(Symbol_table* symtab, Layout* layout, Target_i386* target,
|
||||||
|
@ -1702,15 +1703,19 @@ Target_i386::Scan::reloc_needs_plt_for_ifunc(
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
Target_i386::Scan::local(Symbol_table* symtab,
|
Target_i386::Scan::local(Symbol_table* symtab,
|
||||||
Layout* layout,
|
Layout* layout,
|
||||||
Target_i386* target,
|
Target_i386* target,
|
||||||
Sized_relobj_file<32, false>* object,
|
Sized_relobj_file<32, false>* object,
|
||||||
unsigned int data_shndx,
|
unsigned int data_shndx,
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rel<32, false>& reloc,
|
const elfcpp::Rel<32, false>& reloc,
|
||||||
unsigned int r_type,
|
unsigned int r_type,
|
||||||
const elfcpp::Sym<32, false>& lsym)
|
const elfcpp::Sym<32, false>& lsym,
|
||||||
|
bool is_discarded)
|
||||||
{
|
{
|
||||||
|
if (is_discarded)
|
||||||
|
return;
|
||||||
|
|
||||||
// A local STT_GNU_IFUNC symbol may require a PLT entry.
|
// A local STT_GNU_IFUNC symbol may require a PLT entry.
|
||||||
if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC
|
if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC
|
||||||
&& this->reloc_needs_plt_for_ifunc(object, r_type))
|
&& this->reloc_needs_plt_for_ifunc(object, r_type))
|
||||||
|
|
178
gold/powerpc.cc
178
gold/powerpc.cc
|
@ -65,8 +65,7 @@ public:
|
||||||
Powerpc_relobj(const std::string& name, Input_file* input_file, off_t offset,
|
Powerpc_relobj(const std::string& name, Input_file* input_file, off_t offset,
|
||||||
const typename elfcpp::Ehdr<size, big_endian>& ehdr)
|
const typename elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||||
: Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
|
: Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
|
||||||
special_(0), opd_ent_shndx_(), opd_ent_off_(), access_from_map_(),
|
special_(0), opd_valid_(false), opd_ent_(), access_from_map_()
|
||||||
opd_valid_(false)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~Powerpc_relobj()
|
~Powerpc_relobj()
|
||||||
|
@ -97,8 +96,7 @@ public:
|
||||||
init_opd(size_t opd_size)
|
init_opd(size_t opd_size)
|
||||||
{
|
{
|
||||||
size_t count = this->opd_ent_ndx(opd_size);
|
size_t count = this->opd_ent_ndx(opd_size);
|
||||||
this->opd_ent_shndx_.resize(count);
|
this->opd_ent_.resize(count);
|
||||||
this->opd_ent_off_.reserve(count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return section and offset of function entry for .opd + R_OFF.
|
// Return section and offset of function entry for .opd + R_OFF.
|
||||||
|
@ -106,11 +104,11 @@ public:
|
||||||
get_opd_ent(Address r_off, Address* value = NULL) const
|
get_opd_ent(Address r_off, Address* value = NULL) const
|
||||||
{
|
{
|
||||||
size_t ndx = this->opd_ent_ndx(r_off);
|
size_t ndx = this->opd_ent_ndx(r_off);
|
||||||
gold_assert(ndx < this->opd_ent_shndx_.size());
|
gold_assert(ndx < this->opd_ent_.size());
|
||||||
gold_assert(this->opd_ent_shndx_[ndx] != 0);
|
gold_assert(this->opd_ent_[ndx].shndx != 0);
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
*value = this->opd_ent_off_[ndx];
|
*value = this->opd_ent_[ndx].off;
|
||||||
return this->opd_ent_shndx_[ndx];
|
return this->opd_ent_[ndx].shndx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set section and offset of function entry for .opd + R_OFF.
|
// Set section and offset of function entry for .opd + R_OFF.
|
||||||
|
@ -118,9 +116,27 @@ public:
|
||||||
set_opd_ent(Address r_off, unsigned int shndx, Address value)
|
set_opd_ent(Address r_off, unsigned int shndx, Address value)
|
||||||
{
|
{
|
||||||
size_t ndx = this->opd_ent_ndx(r_off);
|
size_t ndx = this->opd_ent_ndx(r_off);
|
||||||
gold_assert(ndx < this->opd_ent_shndx_.size());
|
gold_assert(ndx < this->opd_ent_.size());
|
||||||
this->opd_ent_shndx_[ndx] = shndx;
|
this->opd_ent_[ndx].shndx = shndx;
|
||||||
this->opd_ent_off_[ndx] = value;
|
this->opd_ent_[ndx].off = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return discard flag for .opd + R_OFF.
|
||||||
|
bool
|
||||||
|
get_opd_discard(Address r_off) const
|
||||||
|
{
|
||||||
|
size_t ndx = this->opd_ent_ndx(r_off);
|
||||||
|
gold_assert(ndx < this->opd_ent_.size());
|
||||||
|
return this->opd_ent_[ndx].discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set discard flag for .opd + R_OFF.
|
||||||
|
void
|
||||||
|
set_opd_discard(Address r_off)
|
||||||
|
{
|
||||||
|
size_t ndx = this->opd_ent_ndx(r_off);
|
||||||
|
gold_assert(ndx < this->opd_ent_.size());
|
||||||
|
this->opd_ent_[ndx].discard = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Access_from*
|
Access_from*
|
||||||
|
@ -165,38 +181,47 @@ public:
|
||||||
{ return 0x8000; }
|
{ return 0x8000; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Return index into opd_ent_shndx or opd_ent_off array for .opd entry
|
struct Opd_ent
|
||||||
// at OFF. .opd entries are 24 bytes long, but they can be spaced
|
{
|
||||||
// 16 bytes apart when the language doesn't use the last 8-byte
|
unsigned int shndx;
|
||||||
// word, the environment pointer. Thus dividing the entry section
|
bool discard;
|
||||||
// offset by 16 will give an index into opd_ent_shndx_ and
|
Offset off;
|
||||||
// opd_ent_off_ that works for either layout of .opd. (It leaves
|
};
|
||||||
// some elements of the vectors unused when .opd entries are spaced
|
|
||||||
// 24 bytes apart, but we don't know the spacing until relocations
|
// Return index into opd_ent_ array for .opd entry at OFF.
|
||||||
// are processed, and in any case it is possible for an object to
|
// .opd entries are 24 bytes long, but they can be spaced 16 bytes
|
||||||
// have some entries spaced 16 bytes apart and others 24 bytes apart.)
|
// apart when the language doesn't use the last 8-byte word, the
|
||||||
|
// environment pointer. Thus dividing the entry section offset by
|
||||||
|
// 16 will give an index into opd_ent_ that works for either layout
|
||||||
|
// of .opd. (It leaves some elements of the vector unused when .opd
|
||||||
|
// entries are spaced 24 bytes apart, but we don't know the spacing
|
||||||
|
// until relocations are processed, and in any case it is possible
|
||||||
|
// for an object to have some entries spaced 16 bytes apart and
|
||||||
|
// others 24 bytes apart.)
|
||||||
size_t
|
size_t
|
||||||
opd_ent_ndx(size_t off) const
|
opd_ent_ndx(size_t off) const
|
||||||
{ return off >> 4;}
|
{ return off >> 4;}
|
||||||
|
|
||||||
// For 32-bit the .got2 section shdnx, for 64-bit the .opd section shndx.
|
// For 32-bit the .got2 section shdnx, for 64-bit the .opd section shndx.
|
||||||
unsigned int special_;
|
unsigned int special_;
|
||||||
// The first 8-byte word of an OPD entry gives the address of the
|
|
||||||
// entry point of the function. Relocatable object files have a
|
// Set at the start of gc_process_relocs, when we know opd_ent_
|
||||||
// relocation on this word. The following two vectors record the
|
// vector is valid. The flag could be made atomic and set in
|
||||||
// section and offset specified by these relocations.
|
|
||||||
std::vector<unsigned int> opd_ent_shndx_;
|
|
||||||
std::vector<Offset> opd_ent_off_;
|
|
||||||
// References made to this object's .opd section when running
|
|
||||||
// gc_process_relocs for another object, before the opd_ent vectors
|
|
||||||
// are valid for this object.
|
|
||||||
Access_from access_from_map_;
|
|
||||||
// Set at the start of gc_process_relocs, when we know opd_ent
|
|
||||||
// vectors are valid. The flag could be made atomic and set in
|
|
||||||
// do_read_relocs with memory_order_release and then tested with
|
// do_read_relocs with memory_order_release and then tested with
|
||||||
// memory_order_acquire, potentially resulting in fewer entries in
|
// memory_order_acquire, potentially resulting in fewer entries in
|
||||||
// access_from_map_.
|
// access_from_map_.
|
||||||
bool opd_valid_;
|
bool opd_valid_;
|
||||||
|
|
||||||
|
// The first 8-byte word of an OPD entry gives the address of the
|
||||||
|
// entry point of the function. Relocatable object files have a
|
||||||
|
// relocation on this word. The following vector records the
|
||||||
|
// section and offset specified by these relocations.
|
||||||
|
std::vector<Opd_ent> opd_ent_;
|
||||||
|
|
||||||
|
// References made to this object's .opd section when running
|
||||||
|
// gc_process_relocs for another object, before the opd_ent_ vector
|
||||||
|
// is valid for this object.
|
||||||
|
Access_from access_from_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
|
@ -413,6 +438,8 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
||||||
class Scan
|
class Scan
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
|
||||||
|
|
||||||
Scan()
|
Scan()
|
||||||
: issued_non_pic_error_(false)
|
: issued_non_pic_error_(false)
|
||||||
{ }
|
{ }
|
||||||
|
@ -426,7 +453,8 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
||||||
unsigned int data_shndx,
|
unsigned int data_shndx,
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
|
const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
|
||||||
const elfcpp::Sym<size, big_endian>& lsym);
|
const elfcpp::Sym<size, big_endian>& lsym,
|
||||||
|
bool is_discarded);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
global(Symbol_table* symtab, Layout* layout, Target_powerpc* target,
|
global(Symbol_table* symtab, Layout* layout, Target_powerpc* target,
|
||||||
|
@ -2361,11 +2389,21 @@ Target_powerpc<size, big_endian>::Scan::local(
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rela<size, big_endian>& reloc,
|
const elfcpp::Rela<size, big_endian>& reloc,
|
||||||
unsigned int r_type,
|
unsigned int r_type,
|
||||||
const elfcpp::Sym<size, big_endian>& /* lsym */)
|
const elfcpp::Sym<size, big_endian>& /* lsym */,
|
||||||
|
bool is_discarded)
|
||||||
{
|
{
|
||||||
Powerpc_relobj<size, big_endian>* ppc_object
|
Powerpc_relobj<size, big_endian>* ppc_object
|
||||||
= static_cast<Powerpc_relobj<size, big_endian>*>(object);
|
= static_cast<Powerpc_relobj<size, big_endian>*>(object);
|
||||||
|
|
||||||
|
if (is_discarded)
|
||||||
|
{
|
||||||
|
if (size == 64
|
||||||
|
&& data_shndx == ppc_object->opd_shndx()
|
||||||
|
&& r_type == elfcpp::R_PPC64_ADDR64)
|
||||||
|
ppc_object->set_opd_discard(reloc.get_r_offset());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
case elfcpp::R_POWERPC_NONE:
|
case elfcpp::R_POWERPC_NONE:
|
||||||
|
@ -2382,13 +2420,19 @@ Target_powerpc<size, big_endian>::Scan::local(
|
||||||
= target->got_section(symtab, layout);
|
= target->got_section(symtab, layout);
|
||||||
if (parameters->options().output_is_position_independent())
|
if (parameters->options().output_is_position_independent())
|
||||||
{
|
{
|
||||||
|
Address off = reloc.get_r_offset();
|
||||||
|
if (size == 64
|
||||||
|
&& data_shndx == ppc_object->opd_shndx()
|
||||||
|
&& ppc_object->get_opd_discard(off - 8))
|
||||||
|
break;
|
||||||
|
|
||||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||||
|
Powerpc_relobj<size, big_endian>* symobj = ppc_object;
|
||||||
rela_dyn->add_output_section_relative(got->output_section(),
|
rela_dyn->add_output_section_relative(got->output_section(),
|
||||||
elfcpp::R_POWERPC_RELATIVE,
|
elfcpp::R_POWERPC_RELATIVE,
|
||||||
output_section,
|
output_section,
|
||||||
object, data_shndx,
|
object, data_shndx, off,
|
||||||
reloc.get_r_offset(),
|
symobj->toc_base_offset());
|
||||||
ppc_object->toc_base_offset());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2658,6 +2702,12 @@ Target_powerpc<size, big_endian>::Scan::global(
|
||||||
= target->got_section(symtab, layout);
|
= target->got_section(symtab, layout);
|
||||||
if (parameters->options().output_is_position_independent())
|
if (parameters->options().output_is_position_independent())
|
||||||
{
|
{
|
||||||
|
Address off = reloc.get_r_offset();
|
||||||
|
if (size == 64
|
||||||
|
&& data_shndx == ppc_object->opd_shndx()
|
||||||
|
&& ppc_object->get_opd_discard(off - 8))
|
||||||
|
break;
|
||||||
|
|
||||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||||
Powerpc_relobj<size, big_endian>* symobj = ppc_object;
|
Powerpc_relobj<size, big_endian>* symobj = ppc_object;
|
||||||
if (data_shndx != ppc_object->opd_shndx())
|
if (data_shndx != ppc_object->opd_shndx())
|
||||||
|
@ -2666,14 +2716,22 @@ Target_powerpc<size, big_endian>::Scan::global(
|
||||||
rela_dyn->add_output_section_relative(got->output_section(),
|
rela_dyn->add_output_section_relative(got->output_section(),
|
||||||
elfcpp::R_POWERPC_RELATIVE,
|
elfcpp::R_POWERPC_RELATIVE,
|
||||||
output_section,
|
output_section,
|
||||||
object, data_shndx,
|
object, data_shndx, off,
|
||||||
reloc.get_r_offset(),
|
|
||||||
symobj->toc_base_offset());
|
symobj->toc_base_offset());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case elfcpp::R_PPC64_ADDR64:
|
case elfcpp::R_PPC64_ADDR64:
|
||||||
|
if (size == 64
|
||||||
|
&& data_shndx == ppc_object->opd_shndx()
|
||||||
|
&& (gsym->is_defined_in_discarded_section()
|
||||||
|
|| gsym->object() != object))
|
||||||
|
{
|
||||||
|
ppc_object->set_opd_discard(reloc.get_r_offset());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Fall thru
|
||||||
case elfcpp::R_PPC64_UADDR64:
|
case elfcpp::R_PPC64_UADDR64:
|
||||||
case elfcpp::R_POWERPC_ADDR32:
|
case elfcpp::R_POWERPC_ADDR32:
|
||||||
case elfcpp::R_POWERPC_UADDR32:
|
case elfcpp::R_POWERPC_UADDR32:
|
||||||
|
@ -4038,6 +4096,43 @@ Target_powerpc<size, big_endian>::relocate_section(
|
||||||
|
|
||||||
gold_assert(sh_type == elfcpp::SHT_RELA);
|
gold_assert(sh_type == elfcpp::SHT_RELA);
|
||||||
|
|
||||||
|
unsigned char *opd_rel = NULL;
|
||||||
|
Powerpc_relobj<size, big_endian>* const object
|
||||||
|
= static_cast<Powerpc_relobj<size, big_endian>*>(relinfo->object);
|
||||||
|
if (size == 64
|
||||||
|
&& relinfo->data_shndx == object->opd_shndx())
|
||||||
|
{
|
||||||
|
// Rewrite opd relocs, omitting those for discarded sections
|
||||||
|
// to silence gold::relocate_section errors.
|
||||||
|
const int reloc_size
|
||||||
|
= Reloc_types<elfcpp::SHT_RELA, size, big_endian>::reloc_size;
|
||||||
|
opd_rel = new unsigned char[reloc_count * reloc_size];
|
||||||
|
const unsigned char* rrel = prelocs;
|
||||||
|
unsigned char* wrel = opd_rel;
|
||||||
|
|
||||||
|
for (size_t i = 0;
|
||||||
|
i < reloc_count;
|
||||||
|
++i, rrel += reloc_size, wrel += reloc_size)
|
||||||
|
{
|
||||||
|
typename Reloc_types<elfcpp::SHT_RELA, size, big_endian>::Reloc
|
||||||
|
reloc(rrel);
|
||||||
|
typename elfcpp::Elf_types<size>::Elf_WXword r_info
|
||||||
|
= reloc.get_r_info();
|
||||||
|
unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
|
||||||
|
Address r_off = reloc.get_r_offset();
|
||||||
|
if (r_type == elfcpp::R_PPC64_TOC)
|
||||||
|
r_off -= 8;
|
||||||
|
bool is_discarded = object->get_opd_discard(r_off);
|
||||||
|
|
||||||
|
// Reloc number is reported in some errors, so keep all relocs.
|
||||||
|
if (is_discarded)
|
||||||
|
memset(wrel, 0, reloc_size);
|
||||||
|
else
|
||||||
|
memcpy(wrel, rrel, reloc_size);
|
||||||
|
}
|
||||||
|
prelocs = opd_rel;
|
||||||
|
}
|
||||||
|
|
||||||
gold::relocate_section<size, big_endian, Powerpc, elfcpp::SHT_RELA,
|
gold::relocate_section<size, big_endian, Powerpc, elfcpp::SHT_RELA,
|
||||||
Powerpc_relocate>(
|
Powerpc_relocate>(
|
||||||
relinfo,
|
relinfo,
|
||||||
|
@ -4050,6 +4145,9 @@ Target_powerpc<size, big_endian>::relocate_section(
|
||||||
address,
|
address,
|
||||||
view_size,
|
view_size,
|
||||||
reloc_symbol_changes);
|
reloc_symbol_changes);
|
||||||
|
|
||||||
|
if (opd_rel != NULL)
|
||||||
|
delete[] opd_rel;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Powerpc_scan_relocatable_reloc
|
class Powerpc_scan_relocatable_reloc
|
||||||
|
|
|
@ -237,7 +237,8 @@ class Target_sparc : public Sized_target<size, big_endian>
|
||||||
unsigned int data_shndx,
|
unsigned int data_shndx,
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
|
const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
|
||||||
const elfcpp::Sym<size, big_endian>& lsym);
|
const elfcpp::Sym<size, big_endian>& lsym,
|
||||||
|
bool is_discarded);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
global(Symbol_table* symtab, Layout* layout, Target_sparc* target,
|
global(Symbol_table* symtab, Layout* layout, Target_sparc* target,
|
||||||
|
@ -2240,8 +2241,12 @@ Target_sparc<size, big_endian>::Scan::local(
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rela<size, big_endian>& reloc,
|
const elfcpp::Rela<size, big_endian>& reloc,
|
||||||
unsigned int r_type,
|
unsigned int r_type,
|
||||||
const elfcpp::Sym<size, big_endian>& lsym)
|
const elfcpp::Sym<size, big_endian>& lsym,
|
||||||
|
bool is_discarded)
|
||||||
{
|
{
|
||||||
|
if (is_discarded)
|
||||||
|
return;
|
||||||
|
|
||||||
bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
|
bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
|
||||||
unsigned int orig_r_type = r_type;
|
unsigned int orig_r_type = r_type;
|
||||||
r_type &= 0xff;
|
r_type &= 0xff;
|
||||||
|
|
|
@ -81,30 +81,25 @@ scan_relocs(
|
||||||
unsigned int shndx = lsym.get_st_shndx();
|
unsigned int shndx = lsym.get_st_shndx();
|
||||||
bool is_ordinary;
|
bool is_ordinary;
|
||||||
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
|
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
|
||||||
if (is_ordinary
|
// If RELOC is a relocation against a local symbol in a
|
||||||
&& shndx != elfcpp::SHN_UNDEF
|
// section we are discarding then we can ignore it. It will
|
||||||
&& !object->is_section_included(shndx)
|
// eventually become a reloc against the value zero.
|
||||||
&& !symtab->is_section_folded(object, shndx))
|
//
|
||||||
{
|
// FIXME: We should issue a warning if this is an
|
||||||
// RELOC is a relocation against a local symbol in a
|
// allocated section; is this the best place to do it?
|
||||||
// section we are discarding. We can ignore this
|
//
|
||||||
// relocation. It will eventually become a reloc
|
// FIXME: The old GNU linker would in some cases look
|
||||||
// against the value zero.
|
// for the linkonce section which caused this section to
|
||||||
//
|
// be discarded, and, if the other section was the same
|
||||||
// FIXME: We should issue a warning if this is an
|
// size, change the reloc to refer to the other section.
|
||||||
// allocated section; is this the best place to do it?
|
// That seems risky and weird to me, and I don't know of
|
||||||
//
|
// any case where it is actually required.
|
||||||
// FIXME: The old GNU linker would in some cases look
|
bool is_discarded = (is_ordinary
|
||||||
// for the linkonce section which caused this section to
|
&& shndx != elfcpp::SHN_UNDEF
|
||||||
// be discarded, and, if the other section was the same
|
&& !object->is_section_included(shndx)
|
||||||
// size, change the reloc to refer to the other section.
|
&& !symtab->is_section_folded(object, shndx));
|
||||||
// That seems risky and weird to me, and I don't know of
|
|
||||||
// any case where it is actually required.
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
scan.local(symtab, layout, target, object, data_shndx,
|
scan.local(symtab, layout, target, object, data_shndx,
|
||||||
output_section, reloc, r_type, lsym);
|
output_section, reloc, r_type, lsym, is_discarded);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -676,7 +676,8 @@ class Target_x86_64 : public Sized_target<size, false>
|
||||||
unsigned int data_shndx,
|
unsigned int data_shndx,
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rela<size, false>& reloc, unsigned int r_type,
|
const elfcpp::Rela<size, false>& reloc, unsigned int r_type,
|
||||||
const elfcpp::Sym<size, false>& lsym);
|
const elfcpp::Sym<size, false>& lsym,
|
||||||
|
bool is_discarded);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
global(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
|
global(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
|
||||||
|
@ -2270,8 +2271,12 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
|
||||||
Output_section* output_section,
|
Output_section* output_section,
|
||||||
const elfcpp::Rela<size, false>& reloc,
|
const elfcpp::Rela<size, false>& reloc,
|
||||||
unsigned int r_type,
|
unsigned int r_type,
|
||||||
const elfcpp::Sym<size, false>& lsym)
|
const elfcpp::Sym<size, false>& lsym,
|
||||||
|
bool is_discarded)
|
||||||
{
|
{
|
||||||
|
if (is_discarded)
|
||||||
|
return;
|
||||||
|
|
||||||
// A local STT_GNU_IFUNC symbol may require a PLT entry.
|
// A local STT_GNU_IFUNC symbol may require a PLT entry.
|
||||||
bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
|
bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
|
||||||
if (is_ifunc && this->reloc_needs_plt_for_ifunc(object, r_type))
|
if (is_ifunc && this->reloc_needs_plt_for_ifunc(object, r_type))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue