class Output_section;
class Output_file;
class Output_symtab_xindex;
+class Pluginobj;
class Dynobj;
class Object_merge_map;
class Relocatable_relocs;
is_dynamic() const
{ return this->is_dynamic_; }
+ // Returns NULL for Objects that are not plugin objects. This method
+ // is overridden in the Pluginobj class.
+ Pluginobj*
+ pluginobj()
+ { return this->do_pluginobj(); }
+
// Return the target structure associated with this object.
Target*
target() const
// Read data from the underlying file.
void
- read(off_t start, section_size_type size, void* p) const
+ read(off_t start, section_size_type size, void* p)
{ this->input_file()->file().read(start + this->offset_, size, p); }
// Read multiple data from the underlying file.
size_t* used) const
{ this->do_get_global_symbol_counts(symtab, defined, used); }
+ // Set the target.
+ void
+ set_target(Target* target)
+ { this->target_ = target; }
+
protected:
+ // Returns NULL for Objects that are not plugin objects. This method
+ // is overridden in the Pluginobj class.
+ virtual Pluginobj*
+ do_pluginobj()
+ { return NULL; }
+
// Read the symbols--implemented by child class.
virtual void
do_read_symbols(Read_symbols_data*) = 0;
{ return this->do_output_section_offset(shndx); }
// Set the offset of an input section within its output section.
- virtual void
+ void
set_section_offset(unsigned int shndx, uint64_t off)
{ this->do_set_section_offset(shndx, off); }
return (*this->map_to_relocatable_relocs_)[reloc_shndx];
}
+ // Layout sections whose layout was deferred while waiting for
+ // input files from a plugin.
+ void
+ layout_deferred_sections(Layout* layout)
+ { this->do_layout_deferred_sections(layout); }
+
protected:
// The output section to be used for each input section, indexed by
// the input section number. The output section is NULL if the
virtual void
do_set_section_offset(unsigned int shndx, uint64_t off) = 0;
+ // Layout sections whose layout was deferred while waiting for
+ // input files from a plugin--implemented by child class.
+ virtual void
+ do_layout_deferred_sections(Layout*) = 0;
+
// Return the vector mapping input sections to output sections.
Output_sections&
output_sections()
Value
value(const Relobj* object, unsigned int input_shndx, Value addend) const
{
- Value input_offset = this->input_value_ + addend;
+ // This is a relocation against a section symbol. ADDEND is the
+ // offset in the section. The result should be the start of some
+ // merge area. If the object file wants something else, it should
+ // use a regular symbol rather than a section symbol.
+ // Unfortunately, PR 6658 shows a case in which the object file
+ // refers to the section symbol, but uses a negative ADDEND to
+ // compensate for a PC relative reloc. We can't handle the
+ // general case. However, we can handle the special case of a
+ // negative addend, by assuming that it refers to the start of the
+ // section. Of course, that means that we have to guess when
+ // ADDEND is negative. It is normal to see a 32-bit value here
+ // even when the template parameter size is 64, as 64-bit object
+ // file formats have 32-bit relocations. We know this is a merge
+ // section, so we know it has to fit into memory. So we assume
+ // that we won't see a value larger than a large 32-bit unsigned
+ // value. This will break objects with very very large merge
+ // sections; they probably break in other ways anyhow.
+ Value input_offset = this->input_value_;
+ if (addend < 0xffffff00)
+ {
+ input_offset += addend;
+ addend = 0;
+ }
typename Output_addresses::const_iterator p =
this->output_addresses_.find(input_offset);
if (p != this->output_addresses_.end())
- return p->second;
+ return p->second + addend;
- return this->value_from_output_section(object, input_shndx, input_offset);
+ return (this->value_from_output_section(object, input_shndx, input_offset)
+ + addend);
}
private:
typedef std::vector<Symbol*> Symbols;
typedef std::vector<Symbol_value<size> > Local_values;
+ static const Address invalid_address = static_cast<Address>(0) - 1;
+
Sized_relobj(const std::string& name, Input_file* input_file, off_t offset,
const typename elfcpp::Ehdr<size, big_endian>&);
void
do_layout(Symbol_table*, Layout*, Read_symbols_data*);
+ // Layout sections whose layout was deferred while waiting for
+ // input files from a plugin.
+ void
+ do_layout_deferred_sections(Layout*);
+
// Add the symbols to the symbol table.
void
do_add_symbols(Symbol_table*, Read_symbols_data*);
// Get the offset of a section.
uint64_t
do_output_section_offset(unsigned int shndx) const
- { return this->get_output_section_offset(shndx); }
+ {
+ Address off = this->get_output_section_offset(shndx);
+ if (off == invalid_address)
+ return -1ULL;
+ return off;
+ }
// Set the offset of a section.
void
include_linkonce_section(Layout*, unsigned int, const char*,
const elfcpp::Shdr<size, big_endian>&);
+ // Layout an input section.
+ void
+ layout_section(Layout* layout, unsigned int shndx, const char* name,
+ typename This::Shdr& shdr, unsigned int reloc_shndx,
+ unsigned int reloc_type);
+
// Views and sizes when relocating.
struct View_size
{
};
typedef Unordered_map<unsigned int, Tls_got_entry> Local_tls_got_offsets;
+ // Saved information for sections whose layout was deferred.
+ struct Deferred_layout
+ {
+ static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
+ Deferred_layout(unsigned int shndx, const char* name,
+ const unsigned char* pshdr,
+ unsigned int reloc_shndx, unsigned int reloc_type)
+ : shndx_(shndx), name_(name), reloc_shndx_(reloc_shndx),
+ reloc_type_(reloc_type)
+ {
+ memcpy(this->shdr_data_, pshdr, shdr_size);
+ }
+ unsigned int shndx_;
+ std::string name_;
+ unsigned int reloc_shndx_;
+ unsigned int reloc_type_;
+ unsigned char shdr_data_[shdr_size];
+ };
+
// General access to the ELF file.
elfcpp::Elf_file<size, big_endian, Object> elf_file_;
// Index of SHT_SYMTAB section.
// for TLS symbols, indexed by symbol number.
Local_got_offsets local_got_offsets_;
// For each input section, the offset of the input section in its
- // output section. This is -1U if the input section requires a
+ // output section. This is INVALID_ADDRESS if the input section requires a
// special mapping.
std::vector<Address> section_offsets_;
// Table mapping discarded comdat sections to corresponding kept sections.
Comdat_group_table comdat_groups_;
// Whether this object has a GNU style .eh_frame section.
bool has_eh_frame_;
+ // The list of sections whose layout was deferred.
+ std::vector<Deferred_layout> deferred_layout_;
};
// A class to manage the list of all objects.