* 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:
Alan Modra 2012-08-11 04:41:28 +00:00
parent bad7670a0e
commit cf43a2fe99
6 changed files with 1376 additions and 608 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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,

View File

@ -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.

View File

@ -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_;

File diff suppressed because it is too large Load Diff