* object.h (Sized_relobj_file::adjust_local_symbol,
do_adjust_local_symbol): New functions. * object.cc (Sized_relobj_file::do_count_local_symbols): Use the above. * powerpc.cc (Powerpc_relobj::do_adjust_local_symbol): New function. (Powerpc_relobj::scan_opd_relocs): Warn on unexpected opd relocs and irregular opd entry spacing. (Powerpc_relobj::do_read_relocs): Add opd size checks. (Global_symbol_visitor_opd): New functor. (Target_powerpc::do_finalize_sections): Omit global symbols defined on deleted opd entries.
This commit is contained in:
parent
a1e5fd6938
commit
ec4dbad32d
@ -1,3 +1,16 @@
|
||||
2012-09-25 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* object.h (Sized_relobj_file::adjust_local_symbol,
|
||||
do_adjust_local_symbol): New functions.
|
||||
* object.cc (Sized_relobj_file::do_count_local_symbols): Use the above.
|
||||
* powerpc.cc (Powerpc_relobj::do_adjust_local_symbol): New function.
|
||||
(Powerpc_relobj::scan_opd_relocs): Warn on unexpected opd relocs
|
||||
and irregular opd entry spacing.
|
||||
(Powerpc_relobj::do_read_relocs): Add opd size checks.
|
||||
(Global_symbol_visitor_opd): New functor.
|
||||
(Target_powerpc::do_finalize_sections): Omit global symbols defined
|
||||
on deleted opd entries.
|
||||
|
||||
2012-09-15 Jiong Wang <jiwang@tilera.com>
|
||||
|
||||
* tilegx.cc: New file.
|
||||
|
@ -2110,7 +2110,8 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sym.get_st_type() == elfcpp::STT_SECTION)
|
||||
if (sym.get_st_type() == elfcpp::STT_SECTION
|
||||
|| !this->adjust_local_symbol(&lv))
|
||||
{
|
||||
lv.set_no_output_symtab_entry();
|
||||
gold_assert(!lv.needs_output_dynsym_entry());
|
||||
|
@ -2112,6 +2112,12 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
||||
void
|
||||
set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
|
||||
|
||||
// Adjust this local symbol value. Return false if the symbol
|
||||
// should be discarded from the output file.
|
||||
bool
|
||||
adjust_local_symbol(Symbol_value<size>* lv) const
|
||||
{ return this->do_adjust_local_symbol(lv); }
|
||||
|
||||
// Return the name of the symbol that spans the given offset in the
|
||||
// specified section in this object. This is used only for error
|
||||
// messages and is not particularly efficient.
|
||||
@ -2381,6 +2387,12 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
||||
const unsigned char* pshdrs, Output_file* of,
|
||||
Views* pviews);
|
||||
|
||||
// Adjust this local symbol value. Return false if the symbol
|
||||
// should be discarded from the output file.
|
||||
virtual bool
|
||||
do_adjust_local_symbol(Symbol_value<size>*) const
|
||||
{ return true; }
|
||||
|
||||
// Allow a child to set output local symbol count.
|
||||
void
|
||||
set_output_local_symbol_count(unsigned int value)
|
||||
|
@ -174,6 +174,22 @@ public:
|
||||
bool
|
||||
do_find_special_sections(Read_symbols_data* sd);
|
||||
|
||||
// Adjust this local symbol value. Return false if the symbol
|
||||
// should be discarded from the output file.
|
||||
bool
|
||||
do_adjust_local_symbol(Symbol_value<size>* lv) const
|
||||
{
|
||||
if (size == 64 && this->opd_shndx() != 0)
|
||||
{
|
||||
bool is_ordinary;
|
||||
if (lv->input_shndx(&is_ordinary) != this->opd_shndx())
|
||||
return true;
|
||||
if (this->get_opd_discard(lv->input_value()))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return offset in output GOT section that this object will use
|
||||
// as a TOC pointer. Won't be just a constant with multi-toc support.
|
||||
Address
|
||||
@ -1183,6 +1199,9 @@ Powerpc_relobj<size, big_endian>::scan_opd_relocs(
|
||||
const int reloc_size
|
||||
= Reloc_types<elfcpp::SHT_RELA, size, big_endian>::reloc_size;
|
||||
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
|
||||
Address expected_off = 0;
|
||||
bool regular = true;
|
||||
unsigned int opd_ent_size = 0;
|
||||
|
||||
for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
|
||||
{
|
||||
@ -1209,7 +1228,36 @@ Powerpc_relobj<size, big_endian>::scan_opd_relocs(
|
||||
&is_ordinary);
|
||||
this->set_opd_ent(reloc.get_r_offset(), shndx,
|
||||
value + reloc.get_r_addend());
|
||||
if (i == 2)
|
||||
{
|
||||
expected_off = reloc.get_r_offset();
|
||||
opd_ent_size = expected_off;
|
||||
}
|
||||
else if (expected_off != reloc.get_r_offset())
|
||||
regular = false;
|
||||
expected_off += opd_ent_size;
|
||||
}
|
||||
else if (r_type == elfcpp::R_PPC64_TOC)
|
||||
{
|
||||
if (expected_off - opd_ent_size + 8 != reloc.get_r_offset())
|
||||
regular = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
gold_warning(_("%s: unexpected reloc type %u in .opd section"),
|
||||
this->name().c_str(), r_type);
|
||||
regular = false;
|
||||
}
|
||||
}
|
||||
if (reloc_count <= 2)
|
||||
opd_ent_size = this->section_size(this->opd_shndx());
|
||||
if (opd_ent_size != 24 && opd_ent_size != 16)
|
||||
regular = false;
|
||||
if (!regular)
|
||||
{
|
||||
gold_warning(_("%s: .opd is not a regular array of opd entries"),
|
||||
this->name().c_str());
|
||||
opd_ent_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1227,9 +1275,14 @@ Powerpc_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||
{
|
||||
if (p->data_shndx == this->opd_shndx())
|
||||
{
|
||||
this->init_opd(this->section_size(this->opd_shndx()));
|
||||
this->scan_opd_relocs(p->reloc_count, p->contents->data(),
|
||||
rd->local_symbols->data());
|
||||
uint64_t opd_size = this->section_size(this->opd_shndx());
|
||||
gold_assert(opd_size == static_cast<size_t>(opd_size));
|
||||
if (opd_size != 0)
|
||||
{
|
||||
this->init_opd(opd_size);
|
||||
this->scan_opd_relocs(p->reloc_count, p->contents->data(),
|
||||
rd->local_symbols->data());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3204,6 +3257,38 @@ Target_powerpc<size, big_endian>::scan_relocs(
|
||||
plocal_symbols);
|
||||
}
|
||||
|
||||
// Functor class for processing the global symbol table.
|
||||
// Removes symbols defined on discarded opd entries.
|
||||
|
||||
template<bool big_endian>
|
||||
class Global_symbol_visitor_opd
|
||||
{
|
||||
public:
|
||||
Global_symbol_visitor_opd()
|
||||
{ }
|
||||
|
||||
void
|
||||
operator()(Sized_symbol<64>* sym)
|
||||
{
|
||||
if (sym->has_symtab_index()
|
||||
|| sym->source() != Symbol::FROM_OBJECT
|
||||
|| !sym->in_real_elf())
|
||||
return;
|
||||
|
||||
Powerpc_relobj<64, big_endian>* symobj
|
||||
= static_cast<Powerpc_relobj<64, big_endian>*>(sym->object());
|
||||
if (symobj->is_dynamic()
|
||||
|| symobj->opd_shndx() == 0)
|
||||
return;
|
||||
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = sym->shndx(&is_ordinary);
|
||||
if (shndx == symobj->opd_shndx()
|
||||
&& symobj->get_opd_discard(sym->value()))
|
||||
sym->set_symtab_index(-1U);
|
||||
}
|
||||
};
|
||||
|
||||
// Finalize the sections.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
@ -3211,8 +3296,14 @@ void
|
||||
Target_powerpc<size, big_endian>::do_finalize_sections(
|
||||
Layout* layout,
|
||||
const Input_objects*,
|
||||
Symbol_table*)
|
||||
Symbol_table* symtab)
|
||||
{
|
||||
if (size == 64)
|
||||
{
|
||||
typedef Global_symbol_visitor_opd<big_endian> Symbol_visitor;
|
||||
symtab->for_all_symbols<64, Symbol_visitor>(Symbol_visitor());
|
||||
}
|
||||
|
||||
// Fill in some more dynamic tags.
|
||||
const Reloc_section* rel_plt = (this->plt_ == NULL
|
||||
? NULL
|
||||
|
Loading…
x
Reference in New Issue
Block a user