diff options
author | Alan Modra <amodra@gmail.com> | 2012-08-11 04:41:28 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2012-08-11 04:41:28 +0000 |
commit | cf43a2fe99107aae4bfdf9bae8380729fb2c7b64 (patch) | |
tree | 8bc1af6d3b4dca7f1e671eea1fbe8b7bfb7bf236 /gold/object.cc | |
parent | bad7670a0e26d425d660376c6ac3ccc867783d32 (diff) | |
download | gdb-cf43a2fe99107aae4bfdf9bae8380729fb2c7b64.zip gdb-cf43a2fe99107aae4bfdf9bae8380729fb2c7b64.tar.gz gdb-cf43a2fe99107aae4bfdf9bae8380729fb2c7b64.tar.bz2 |
* 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.
Diffstat (limited to 'gold/object.cc')
-rw-r--r-- | gold/object.cc | 133 |
1 files changed, 95 insertions, 38 deletions
diff --git a/gold/object.cc b/gold/object.cc index e43ffdc..fc8533e 100644 --- a/gold/object.cc +++ b/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) + const unsigned char* s = NULL; + + while (1) { - 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; - } + s = this->find_shdr(pshdrs, ".eh_frame", names, names_size, s); + if (s == NULL) + return false; - const char* name = names + shdr.get_sh_name(); - if (strcmp(name, ".eh_frame") == 0) - return true; - } + 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; |