// object.cc -- support for an object file for linking in gold
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// Struct Read_symbols_data.
-// Destroy any remaining File_view objects.
+// Destroy any remaining File_view objects and buffers of decompressed
+// sections.
Read_symbols_data::~Read_symbols_data()
{
|| (is_prefix_of(".text", name)
&& strstr(name, "personality"))
|| (is_prefix_of(".data", name)
- && strstr(name, "personality"))
+ && strstr(name, "personality"))
+ || (is_prefix_of(".sdata", name)
+ && strstr(name, "personality"))
|| (is_prefix_of(".gnu.linkonce.d", name)
&& strstr(name, "personality")))
{
}
}
+// Get the address of an output section.
+
+template<int size, bool big_endian>
+uint64_t
+Sized_relobj<size, big_endian>::do_output_section_address(
+ unsigned int shndx)
+{
+ // If the input file is linked as --just-symbols, the output
+ // section address is the input section address.
+ if (this->just_symbols())
+ return this->section_address(shndx);
+
+ const Output_section* os = this->do_output_section(shndx);
+ gold_assert(os != NULL);
+ return os->address();
+}
+
// Class Sized_relobj_file.
template<int size, bool big_endian>
template<int size, bool big_endian>
const unsigned char*
-Sized_relobj_file<size, big_endian>::find_shdr(
+Object::find_shdr(
const unsigned char* pshdrs,
const char* name,
const char* names,
section_size_type names_size,
const unsigned char* hdr) const
{
+ const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
const unsigned int shnum = this->shnum();
- const unsigned char* hdr_end = pshdrs + This::shdr_size * shnum;
+ const unsigned char* hdr_end = pshdrs + 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);
+ typename elfcpp::Shdr<size, big_endian> shdr(hdr);
sh_name = shdr.get_sh_name();
}
else
return hdr;
}
- hdr += This::shdr_size;
+ hdr += shdr_size;
while (hdr < hdr_end)
{
- typename This::Shdr shdr(hdr);
+ typename elfcpp::Shdr<size, big_endian> shdr(hdr);
if (shdr.get_sh_name() == sh_name)
return hdr;
- hdr += This::shdr_size;
+ hdr += shdr_size;
}
hdr = NULL;
if (sh_name == 0)
while (1)
{
- s = this->find_shdr(pshdrs, ".eh_frame", names, names_size, s);
+ s = this->template find_shdr<size, big_endian>(pshdrs, ".eh_frame",
+ names, names_size, s);
if (s == NULL)
return false;
if (!is_pass_two)
layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
+ // Handle the .eh_frame sections after the other sections.
+ gold_assert(!is_pass_one || eh_frame_sections.empty());
+ for (std::vector<unsigned int>::const_iterator p = eh_frame_sections.begin();
+ p != eh_frame_sections.end();
+ ++p)
+ {
+ unsigned int i = *p;
+ const unsigned char* pshdr;
+ pshdr = section_headers_data + i * This::shdr_size;
+ typename This::Shdr shdr(pshdr);
+
+ this->layout_eh_frame_section(layout,
+ symbols_data,
+ symbols_size,
+ symbol_names_data,
+ symbol_names_size,
+ i,
+ shdr,
+ reloc_shndx[i],
+ reloc_type[i]);
+ }
+
// When doing a relocatable link handle the reloc sections at the
// end. Garbage collection and Identical Code Folding is not
// turned on for relocatable code.
out_section_offsets[i] = invalid_address;
}
- // Handle the .eh_frame sections at the end.
- gold_assert(!is_pass_one || eh_frame_sections.empty());
- for (std::vector<unsigned int>::const_iterator p = eh_frame_sections.begin();
- p != eh_frame_sections.end();
- ++p)
- {
- unsigned int i = *p;
- const unsigned char* pshdr;
- pshdr = section_headers_data + i * This::shdr_size;
- typename This::Shdr shdr(pshdr);
-
- this->layout_eh_frame_section(layout,
- symbols_data,
- symbols_size,
- symbol_names_data,
- symbol_names_size,
- i,
- shdr,
- reloc_shndx[i],
- reloc_type[i]);
- }
-
// When building a .gdb_index section, scan the .debug_info and
// .debug_types sections.
gold_assert(!is_pass_one
++deferred)
{
typename This::Shdr shdr(deferred->shdr_data_);
- // If the section is not included, it is because the garbage collector
- // decided it is not needed. Avoid reverting that decision.
- if (!this->is_section_included(deferred->shndx_))
- continue;
- if (parameters->options().relocatable()
- || deferred->name_ != ".eh_frame"
- || !this->check_eh_frame_flags(&shdr))
- this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
- shdr, deferred->reloc_shndx_,
- deferred->reloc_type_);
- else
+ if (!parameters->options().relocatable()
+ && deferred->name_ == ".eh_frame"
+ && this->check_eh_frame_flags(&shdr))
{
+ // Checking is_section_included is not reliable for
+ // .eh_frame sections, because they do not have an output
+ // section. This is not a problem normally because we call
+ // layout_eh_frame_section unconditionally, but when
+ // deferring sections that is not true. We don't want to
+ // keep all .eh_frame sections because that will cause us to
+ // keep all sections that they refer to, which is the wrong
+ // way around. Instead, the eh_frame code will discard
+ // .eh_frame sections that refer to discarded sections.
+
// Reading the symbols again here may be slow.
Read_symbols_data sd;
this->read_symbols(&sd);
shdr,
deferred->reloc_shndx_,
deferred->reloc_type_);
+ continue;
}
+
+ // If the section is not included, it is because the garbage collector
+ // decided it is not needed. Avoid reverting that decision.
+ if (!this->is_section_included(deferred->shndx_))
+ continue;
+
+ this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
+ shdr, deferred->reloc_shndx_,
+ deferred->reloc_type_);
}
this->deferred_layout_.clear();
continue;
}
- if (sym.get_st_type() == elfcpp::STT_SECTION)
+ if (sym.get_st_type() == elfcpp::STT_SECTION
+ || !this->adjust_local_symbol(&lv))
{
lv.set_no_output_symtab_entry();
gold_assert(!lv.needs_output_dynsym_entry());
&& (static_cast<off_t>(sym.get_st_value() + sym.get_st_size())
> offset))
{
+ info->enclosing_symbol_type = sym.get_st_type();
if (sym.get_st_name() > names_size)
info->enclosing_symbol_name = "(invalid)";
else
ret += ":";
ret += info.source_file;
}
- size_t len = info.enclosing_symbol_name.length() + 100;
- char* buf = new char[len];
- snprintf(buf, len, _(":function %s"),
- info.enclosing_symbol_name.c_str());
- ret += buf;
- delete[] buf;
+ ret += ":";
+ if (info.enclosing_symbol_type == elfcpp::STT_FUNC)
+ ret += _("function ");
+ ret += info.enclosing_symbol_name;
return ret;
}
void
Object::read_section_data<32, false>(elfcpp::Elf_file<32, false, Object>*,
Read_symbols_data*);
+template
+const unsigned char*
+Object::find_shdr<32,false>(const unsigned char*, const char*, const char*,
+ section_size_type, const unsigned char*) const;
#endif
#ifdef HAVE_TARGET_32_BIG
void
Object::read_section_data<32, true>(elfcpp::Elf_file<32, true, Object>*,
Read_symbols_data*);
+template
+const unsigned char*
+Object::find_shdr<32,true>(const unsigned char*, const char*, const char*,
+ section_size_type, const unsigned char*) const;
#endif
#ifdef HAVE_TARGET_64_LITTLE
void
Object::read_section_data<64, false>(elfcpp::Elf_file<64, false, Object>*,
Read_symbols_data*);
+template
+const unsigned char*
+Object::find_shdr<64,false>(const unsigned char*, const char*, const char*,
+ section_size_type, const unsigned char*) const;
#endif
#ifdef HAVE_TARGET_64_BIG
void
Object::read_section_data<64, true>(elfcpp::Elf_file<64, true, Object>*,
Read_symbols_data*);
+template
+const unsigned char*
+Object::find_shdr<64,true>(const unsigned char*, const char*, const char*,
+ section_size_type, const unsigned char*) const;
#endif
#ifdef HAVE_TARGET_32_LITTLE
+template
+class Sized_relobj<32, false>;
+
template
class Sized_relobj_file<32, false>;
#endif
#ifdef HAVE_TARGET_32_BIG
+template
+class Sized_relobj<32, true>;
+
template
class Sized_relobj_file<32, true>;
#endif
#ifdef HAVE_TARGET_64_LITTLE
+template
+class Sized_relobj<64, false>;
+
template
class Sized_relobj_file<64, false>;
#endif
#ifdef HAVE_TARGET_64_BIG
+template
+class Sized_relobj<64, true>;
+
template
class Sized_relobj_file<64, true>;
#endif