* object.h (Sized_relobj_file::find_shdr): New function.
(Sized_relobj_file::find_special_sections): New function. * object.cc (Sized_relobj_file::find_shdr): New function. (Sized_relobj_file::find_eh_frame): Use find_shdr. (Sized_relobj_file::find_special_sections): New function, split out.. (Sized_relobj_file::do_read_symbols): ..from here. * output.h (Output_data_got::replace_constant): New function. (Output_data_got::num_entries): New function. (Output_data_got::last_got_offset,set_got_size): Use num_entries. (Output_data_got::got_offset): Protected rather than private. (Output_data_got::replace_got_entry): New function. * output.cc (Output_data_got::replace_got_entry): New function. * powerpc.cc (class Powerpc_relobj): New. (class Powerpc_relocate_functions): Delete all psymval variants or convert to value,addend type. Delete pcrela, pcrela_unaligned. Implement _ha functions using corresponding _hi function. (Powerpc_relobj::find_special_sections): New function. (Target_powerpc::do_make_elf_object): New function. (class Output_data_got_powerpc): New. (class Output_data_glink): New. (class Powerpc_scan_relocatable_reloc): New. Many more changes througout file.
This commit is contained in:
parent
bad7670a0e
commit
cf43a2fe99
|
@ -1,3 +1,28 @@
|
|||
2012-08-11 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* object.h (Sized_relobj_file::find_shdr): New function.
|
||||
(Sized_relobj_file::find_special_sections): New function.
|
||||
* object.cc (Sized_relobj_file::find_shdr): New function.
|
||||
(Sized_relobj_file::find_eh_frame): Use find_shdr.
|
||||
(Sized_relobj_file::find_special_sections): New function, split out..
|
||||
(Sized_relobj_file::do_read_symbols): ..from here.
|
||||
* output.h (Output_data_got::replace_constant): New function.
|
||||
(Output_data_got::num_entries): New function.
|
||||
(Output_data_got::last_got_offset,set_got_size): Use num_entries.
|
||||
(Output_data_got::got_offset): Protected rather than private.
|
||||
(Output_data_got::replace_got_entry): New function.
|
||||
* output.cc (Output_data_got::replace_got_entry): New function.
|
||||
* powerpc.cc (class Powerpc_relobj): New.
|
||||
(class Powerpc_relocate_functions): Delete all psymval variants or
|
||||
convert to value,addend type. Delete pcrela, pcrela_unaligned.
|
||||
Implement _ha functions using corresponding _hi function.
|
||||
(Powerpc_relobj::find_special_sections): New function.
|
||||
(Target_powerpc::do_make_elf_object): New function.
|
||||
(class Output_data_got_powerpc): New.
|
||||
(class Output_data_glink): New.
|
||||
(class Powerpc_scan_relocatable_reloc): New.
|
||||
Many more changes througout file.
|
||||
|
||||
2012-08-09 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* po/vi.po: Updated Vietnamese translation.
|
||||
|
|
135
gold/object.cc
135
gold/object.cc
|
@ -510,6 +510,64 @@ Sized_relobj_file<size, big_endian>::check_eh_frame_flags(
|
|||
&& (shdr->get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
|
||||
}
|
||||
|
||||
// Find the section header with the given name.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
const unsigned char*
|
||||
Sized_relobj_file<size, big_endian>::find_shdr(
|
||||
const unsigned char* pshdrs,
|
||||
const char* name,
|
||||
const char* names,
|
||||
section_size_type names_size,
|
||||
const unsigned char* hdr) const
|
||||
{
|
||||
const unsigned int shnum = this->shnum();
|
||||
const unsigned char* hdr_end = pshdrs + This::shdr_size * shnum;
|
||||
size_t sh_name = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (hdr)
|
||||
{
|
||||
// We found HDR last time we were called, continue looking.
|
||||
typename This::Shdr shdr(hdr);
|
||||
sh_name = shdr.get_sh_name();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for the next occurrence of NAME in NAMES.
|
||||
// The fact that .shstrtab produced by current GNU tools is
|
||||
// string merged means we shouldn't have both .not.foo and
|
||||
// .foo in .shstrtab, and multiple .foo sections should all
|
||||
// have the same sh_name. However, this is not guaranteed
|
||||
// by the ELF spec and not all ELF object file producers may
|
||||
// be so clever.
|
||||
size_t len = strlen(name) + 1;
|
||||
const char *p = sh_name ? names + sh_name + len : names;
|
||||
p = reinterpret_cast<const char*>(memmem(p, names_size - (p - names),
|
||||
name, len));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
sh_name = p - names;
|
||||
hdr = pshdrs;
|
||||
if (sh_name == 0)
|
||||
return hdr;
|
||||
}
|
||||
|
||||
hdr += This::shdr_size;
|
||||
while (hdr < hdr_end)
|
||||
{
|
||||
typename This::Shdr shdr(hdr);
|
||||
if (shdr.get_sh_name() == sh_name)
|
||||
return hdr;
|
||||
hdr += This::shdr_size;
|
||||
}
|
||||
hdr = NULL;
|
||||
if (sh_name == 0)
|
||||
return hdr;
|
||||
}
|
||||
}
|
||||
|
||||
// Return whether there is a GNU .eh_frame section, given the section
|
||||
// headers and the section names.
|
||||
|
||||
|
@ -520,26 +578,18 @@ Sized_relobj_file<size, big_endian>::find_eh_frame(
|
|||
const char* names,
|
||||
section_size_type names_size) const
|
||||
{
|
||||
const unsigned int shnum = this->shnum();
|
||||
const unsigned char* p = pshdrs + This::shdr_size;
|
||||
for (unsigned int i = 1; i < shnum; ++i, p += This::shdr_size)
|
||||
{
|
||||
typename This::Shdr shdr(p);
|
||||
if (this->check_eh_frame_flags(&shdr))
|
||||
{
|
||||
if (shdr.get_sh_name() >= names_size)
|
||||
{
|
||||
this->error(_("bad section name offset for section %u: %lu"),
|
||||
i, static_cast<unsigned long>(shdr.get_sh_name()));
|
||||
continue;
|
||||
}
|
||||
const unsigned char* s = NULL;
|
||||
|
||||
const char* name = names + shdr.get_sh_name();
|
||||
if (strcmp(name, ".eh_frame") == 0)
|
||||
return true;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
s = this->find_shdr(pshdrs, ".eh_frame", names, names_size, s);
|
||||
if (s == NULL)
|
||||
return false;
|
||||
|
||||
typename This::Shdr shdr(s);
|
||||
if (this->check_eh_frame_flags(&shdr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return TRUE if this is a section whose contents will be needed in the
|
||||
|
@ -651,39 +701,46 @@ build_compressed_section_map(
|
|||
return uncompressed_map;
|
||||
}
|
||||
|
||||
// Stash away info for a number of special sections.
|
||||
// Return true if any of the sections found require local symbols to be read.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
bool
|
||||
Sized_relobj_file<size, big_endian>::do_find_special_sections(
|
||||
Read_symbols_data* sd)
|
||||
{
|
||||
const unsigned char* const pshdrs = sd->section_headers->data();
|
||||
const unsigned char* namesu = sd->section_names->data();
|
||||
const char* names = reinterpret_cast<const char*>(namesu);
|
||||
|
||||
if (this->find_eh_frame(pshdrs, names, sd->section_names_size))
|
||||
this->has_eh_frame_ = true;
|
||||
|
||||
if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
|
||||
this->compressed_sections_
|
||||
= build_compressed_section_map(pshdrs, this->shnum(), names,
|
||||
sd->section_names_size, this);
|
||||
return (this->has_eh_frame_
|
||||
|| (!parameters->options().relocatable()
|
||||
&& parameters->options().gdb_index()
|
||||
&& (memmem(names, sd->section_names_size, "debug_info", 12) == 0
|
||||
|| memmem(names, sd->section_names_size, "debug_types",
|
||||
13) == 0)));
|
||||
}
|
||||
|
||||
// Read the sections and symbols from an object file.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
{
|
||||
bool need_local_symbols = false;
|
||||
|
||||
this->read_section_data(&this->elf_file_, sd);
|
||||
|
||||
const unsigned char* const pshdrs = sd->section_headers->data();
|
||||
|
||||
this->find_symtab(pshdrs);
|
||||
|
||||
const unsigned char* namesu = sd->section_names->data();
|
||||
const char* names = reinterpret_cast<const char*>(namesu);
|
||||
if (memmem(names, sd->section_names_size, ".eh_frame", 10) != NULL)
|
||||
{
|
||||
if (this->find_eh_frame(pshdrs, names, sd->section_names_size))
|
||||
this->has_eh_frame_ = true;
|
||||
}
|
||||
if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
|
||||
this->compressed_sections_ =
|
||||
build_compressed_section_map(pshdrs, this->shnum(), names,
|
||||
sd->section_names_size, this);
|
||||
|
||||
if (this->has_eh_frame_
|
||||
|| (!parameters->options().relocatable()
|
||||
&& parameters->options().gdb_index()
|
||||
&& (memmem(names, sd->section_names_size, "debug_info", 12) == 0
|
||||
|| memmem(names, sd->section_names_size, "debug_types",
|
||||
13) == 0)))
|
||||
need_local_symbols = true;
|
||||
bool need_local_symbols = this->do_find_special_sections(sd);
|
||||
|
||||
sd->symbols = NULL;
|
||||
sd->symbols_size = 0;
|
||||
|
|
|
@ -349,7 +349,7 @@ class Object
|
|||
this->input_file_->file().remove_object();
|
||||
}
|
||||
|
||||
// Return the name of the object as we would report it to the tuser.
|
||||
// Return the name of the object as we would report it to the user.
|
||||
const std::string&
|
||||
name() const
|
||||
{ return this->name_; }
|
||||
|
@ -2116,6 +2116,15 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
|||
Address
|
||||
map_to_kept_section(unsigned int shndx, bool* found) const;
|
||||
|
||||
// Find the section header with the given NAME. If HDR is non-NULL
|
||||
// then it is a section header returned from a previous call to this
|
||||
// function and the next section header with the same name will be
|
||||
// returned.
|
||||
const unsigned char*
|
||||
find_shdr(const unsigned char* pshdrs, const char* name,
|
||||
const char* names, section_size_type names_size,
|
||||
const unsigned char* hdr) const;
|
||||
|
||||
// Compute final local symbol value. R_SYM is the local symbol index.
|
||||
// LV_IN points to a local symbol value containing the input value.
|
||||
// LV_OUT points to a local symbol value storing the final output value,
|
||||
|
@ -2347,6 +2356,11 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
|
|||
|
||||
typedef std::vector<View_size> Views;
|
||||
|
||||
// Stash away info for a number of special sections.
|
||||
// Return true if any of the sections found require local symbols to be read.
|
||||
virtual bool
|
||||
do_find_special_sections(Read_symbols_data* sd);
|
||||
|
||||
// This may be overriden by a child class.
|
||||
virtual void
|
||||
do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
|
||||
|
|
|
@ -1701,6 +1701,18 @@ Output_data_got<size, big_endian>::add_got_entry_pair(Got_entry got_entry_1,
|
|||
}
|
||||
}
|
||||
|
||||
// Replace GOT entry I with a new value.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Output_data_got<size, big_endian>::replace_got_entry(
|
||||
unsigned int i,
|
||||
Got_entry got_entry)
|
||||
{
|
||||
gold_assert(i < this->entries_.size());
|
||||
this->entries_[i] = got_entry;
|
||||
}
|
||||
|
||||
// Output_data_dynamic::Dynamic_entry methods.
|
||||
|
||||
// Write out the entry.
|
||||
|
|
|
@ -2257,6 +2257,13 @@ class Output_data_got : public Output_data_got_base
|
|||
return got_offset;
|
||||
}
|
||||
|
||||
// Replace GOT entry I with a new constant.
|
||||
void
|
||||
replace_constant(unsigned int i, Valtype constant)
|
||||
{
|
||||
this->replace_got_entry(i, Got_entry(constant));
|
||||
}
|
||||
|
||||
// Reserve a slot in the GOT for a local symbol.
|
||||
void
|
||||
reserve_local(unsigned int i, Relobj* object, unsigned int sym_index,
|
||||
|
@ -2281,6 +2288,16 @@ class Output_data_got : public Output_data_got_base
|
|||
do_reserve_slot(unsigned int i)
|
||||
{ this->free_list_.remove(i * got_size / 8, (i + 1) * got_size / 8); }
|
||||
|
||||
// Return the number of words in the GOT.
|
||||
unsigned int
|
||||
num_entries () const
|
||||
{ return this->entries_.size(); }
|
||||
|
||||
// Return the offset into the GOT of GOT entry I.
|
||||
unsigned int
|
||||
got_offset(unsigned int i) const
|
||||
{ return i * (got_size / 8); }
|
||||
|
||||
private:
|
||||
// This POD class holds a single GOT entry.
|
||||
class Got_entry
|
||||
|
@ -2352,20 +2369,19 @@ class Output_data_got : public Output_data_got_base
|
|||
unsigned int
|
||||
add_got_entry_pair(Got_entry got_entry_1, Got_entry got_entry_2);
|
||||
|
||||
// Return the offset into the GOT of GOT entry I.
|
||||
unsigned int
|
||||
got_offset(unsigned int i) const
|
||||
{ return i * (got_size / 8); }
|
||||
// Replace GOT entry I with a new value.
|
||||
void
|
||||
replace_got_entry(unsigned int i, Got_entry got_entry);
|
||||
|
||||
// Return the offset into the GOT of the last entry added.
|
||||
unsigned int
|
||||
last_got_offset() const
|
||||
{ return this->got_offset(this->entries_.size() - 1); }
|
||||
{ return this->got_offset(this->num_entries() - 1); }
|
||||
|
||||
// Set the size of the section.
|
||||
void
|
||||
set_got_size()
|
||||
{ this->set_current_data_size(this->got_offset(this->entries_.size())); }
|
||||
{ this->set_current_data_size(this->got_offset(this->num_entries())); }
|
||||
|
||||
// The list of GOT entries.
|
||||
Got_entries entries_;
|
||||
|
|
1768
gold/powerpc.cc
1768
gold/powerpc.cc
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue