* powerpc.cc (Powerpc_relobj): Delete "Offset" typedef.
(struct Opd_ent): Use "Address" rather than "Offset". (Output_data_got_powerpc::got_base_offset): Return Valtype. (Target_powerpc::got_section): Make public. (Target_powerpc::scan_relocs): Move code setting symbols.. (Powerpc_relobj::do_scan_relocs): ..to here, new function. Create _SDA_BASE_ only when referenced.
This commit is contained in:
parent
5a9db15211
commit
26a4e9cbc4
2 changed files with 75 additions and 43 deletions
|
@ -1,3 +1,13 @@
|
|||
2012-11-05 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* powerpc.cc (Powerpc_relobj): Delete "Offset" typedef.
|
||||
(struct Opd_ent): Use "Address" rather than "Offset".
|
||||
(Output_data_got_powerpc::got_base_offset): Return Valtype.
|
||||
(Target_powerpc::got_section): Make public.
|
||||
(Target_powerpc::scan_relocs): Move code setting symbols..
|
||||
(Powerpc_relobj::do_scan_relocs): ..to here, new function.
|
||||
Create _SDA_BASE_ only when referenced.
|
||||
|
||||
2012-11-02 Roland McGrath <mcgrathr@google.com>
|
||||
|
||||
* i386.cc (Target_i386::relocate_relocs): Remove extraneous typename
|
||||
|
|
108
gold/powerpc.cc
108
gold/powerpc.cc
|
@ -58,7 +58,6 @@ class Powerpc_relobj : public Sized_relobj_file<size, big_endian>
|
|||
{
|
||||
public:
|
||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
|
||||
typedef typename elfcpp::Elf_types<size>::Elf_Off Offset;
|
||||
typedef Unordered_set<Section_id, Section_id_hash> Section_refs;
|
||||
typedef Unordered_map<Address, Section_refs> Access_from;
|
||||
|
||||
|
@ -190,9 +189,17 @@ public:
|
|||
const unsigned char* prelocs,
|
||||
const unsigned char* plocal_syms);
|
||||
|
||||
// Perform the Sized_relobj_file method, then set up opd info from
|
||||
// .opd relocs.
|
||||
void
|
||||
do_read_relocs(Read_relocs_data*);
|
||||
|
||||
// Set up some symbols, then perform Sized_relobj_file method.
|
||||
// Occurs after garbage collection, which is why opd info can't be
|
||||
// set up here.
|
||||
void
|
||||
do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*);
|
||||
|
||||
bool
|
||||
do_find_special_sections(Read_symbols_data* sd);
|
||||
|
||||
|
@ -224,7 +231,7 @@ private:
|
|||
unsigned int shndx;
|
||||
bool discard : 1;
|
||||
bool gc_mark : 1;
|
||||
Offset off;
|
||||
Address off;
|
||||
};
|
||||
|
||||
// Return index into opd_ent_ array for .opd entry at OFF.
|
||||
|
@ -449,6 +456,10 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||
return this->got_;
|
||||
}
|
||||
|
||||
// Get the GOT section, creating it if necessary.
|
||||
Output_data_got_powerpc<size, big_endian>*
|
||||
got_section(Symbol_table*, Layout*);
|
||||
|
||||
Object*
|
||||
do_make_elf_object(const std::string&, Input_file*, off_t,
|
||||
const elfcpp::Ehdr<size, big_endian>&);
|
||||
|
@ -694,10 +705,6 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||
return tls::TLSOPT_TO_LE;
|
||||
}
|
||||
|
||||
// Get the GOT section, creating it if necessary.
|
||||
Output_data_got_powerpc<size, big_endian>*
|
||||
got_section(Symbol_table*, Layout*);
|
||||
|
||||
// Create glink.
|
||||
void
|
||||
make_glink_section(Layout*);
|
||||
|
@ -1374,6 +1381,57 @@ Powerpc_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
|||
}
|
||||
}
|
||||
|
||||
// Set up some symbols, then perform Sized_relobj_file method.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Powerpc_relobj<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Read_relocs_data* rd)
|
||||
{
|
||||
if (size == 32)
|
||||
{
|
||||
// Define a weak hidden _GLOBAL_OFFSET_TABLE_ to ensure it isn't
|
||||
// seen as undefined when scanning relocs (and thus requires
|
||||
// non-relative dynamic relocs). The proper value will be
|
||||
// updated later.
|
||||
Symbol *gotsym = symtab->lookup("_GLOBAL_OFFSET_TABLE_", NULL);
|
||||
if (gotsym != NULL && gotsym->is_undefined())
|
||||
{
|
||||
Target_powerpc<size, big_endian>* target =
|
||||
static_cast<Target_powerpc<size, big_endian>*>(
|
||||
parameters->sized_target<size, big_endian>());
|
||||
Output_data_got_powerpc<size, big_endian>* got
|
||||
= target->got_section(symtab, layout);
|
||||
symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
|
||||
Symbol_table::PREDEFINED,
|
||||
got, 0, 0,
|
||||
elfcpp::STT_OBJECT,
|
||||
elfcpp::STB_WEAK,
|
||||
elfcpp::STV_HIDDEN, 0,
|
||||
false, false);
|
||||
}
|
||||
|
||||
// Define _SDA_BASE_ at the start of the .sdata section + 32768.
|
||||
Symbol *sdasym = symtab->lookup("_SDA_BASE_", NULL);
|
||||
if (sdasym != NULL && sdasym->is_undefined())
|
||||
{
|
||||
Output_data_space* sdata = new Output_data_space(4, "** sdata");
|
||||
Output_section* os
|
||||
= layout->add_output_section_data(".sdata", 0,
|
||||
elfcpp::SHF_ALLOC
|
||||
| elfcpp::SHF_WRITE,
|
||||
sdata, ORDER_SMALL_DATA, false);
|
||||
symtab->define_in_output_data("_SDA_BASE_", NULL,
|
||||
Symbol_table::PREDEFINED,
|
||||
os, 32768, 0, elfcpp::STT_OBJECT,
|
||||
elfcpp::STB_LOCAL, elfcpp::STV_HIDDEN,
|
||||
0, false, false);
|
||||
}
|
||||
}
|
||||
Sized_relobj_file<size, big_endian>::do_scan_relocs(symtab, layout, rd);
|
||||
}
|
||||
|
||||
// Set up PowerPC target specific relobj.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
|
@ -1459,7 +1517,7 @@ public:
|
|||
|
||||
// Offset of base used to access the GOT/TOC.
|
||||
// The got/toc pointer reg will be set to this value.
|
||||
typename elfcpp::Elf_types<size>::Elf_Off
|
||||
Valtype
|
||||
got_base_offset(const Powerpc_relobj<size, big_endian>* object) const
|
||||
{
|
||||
if (size == 32)
|
||||
|
@ -4038,42 +4096,6 @@ Target_powerpc<size, big_endian>::scan_relocs(
|
|||
return;
|
||||
}
|
||||
|
||||
if (size == 32)
|
||||
{
|
||||
// Define a weak hidden _GLOBAL_OFFSET_TABLE_ to ensure it isn't
|
||||
// seen as undefined when scanning relocs (and thus requires
|
||||
// non-relative dynamic relocs). The proper value will be
|
||||
// updated later.
|
||||
Symbol *gotsym = symtab->lookup("_GLOBAL_OFFSET_TABLE_", NULL);
|
||||
if (gotsym != NULL && gotsym->is_undefined())
|
||||
symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
|
||||
Symbol_table::PREDEFINED,
|
||||
this->got_section(symtab, layout), 0, 0,
|
||||
elfcpp::STT_OBJECT,
|
||||
elfcpp::STB_WEAK,
|
||||
elfcpp::STV_HIDDEN, 0,
|
||||
false, false);
|
||||
|
||||
static Output_data_space* sdata;
|
||||
|
||||
// Define _SDA_BASE_ at the start of the .sdata section.
|
||||
if (sdata == NULL)
|
||||
{
|
||||
// layout->find_output_section(".sdata") == NULL
|
||||
sdata = new Output_data_space(4, "** sdata");
|
||||
Output_section* os
|
||||
= layout->add_output_section_data(".sdata", 0,
|
||||
elfcpp::SHF_ALLOC
|
||||
| elfcpp::SHF_WRITE,
|
||||
sdata, ORDER_SMALL_DATA, false);
|
||||
symtab->define_in_output_data("_SDA_BASE_", NULL,
|
||||
Symbol_table::PREDEFINED,
|
||||
os, 32768, 0, elfcpp::STT_OBJECT,
|
||||
elfcpp::STB_LOCAL, elfcpp::STV_HIDDEN,
|
||||
0, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
gold::scan_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan>(
|
||||
symtab,
|
||||
layout,
|
||||
|
|
Loading…
Reference in a new issue