aboutsummaryrefslogtreecommitdiff
path: root/gold/object.cc
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2012-08-11 04:41:28 +0000
committerAlan Modra <amodra@gmail.com>2012-08-11 04:41:28 +0000
commitcf43a2fe99107aae4bfdf9bae8380729fb2c7b64 (patch)
tree8bc1af6d3b4dca7f1e671eea1fbe8b7bfb7bf236 /gold/object.cc
parentbad7670a0e26d425d660376c6ac3ccc867783d32 (diff)
downloadgdb-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.cc133
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;