X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Fobject.h;h=f6ee1b72755b1a0663b02e6a2f00d48ecbb574c2;hb=dfd6917457a3030ea4a4b6356f65216fab92d0b8;hp=fc93abd24d59a54636792217282e39623f618e1d;hpb=0916f9e741d6fd9dab4b0602bef034d01fa71650;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/object.h b/gold/object.h index fc93abd24d..f6ee1b7275 100644 --- a/gold/object.h +++ b/gold/object.h @@ -1,6 +1,6 @@ // object.h -- support for an object file for linking in gold -*- C++ -*- -// Copyright (C) 2006-2015 Free Software Foundation, Inc. +// Copyright (C) 2006-2019 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -39,6 +39,7 @@ class General_options; class Task; class Cref; class Layout; +class Kept_section; class Output_data; class Output_section; class Output_section_data; @@ -315,11 +316,64 @@ class Got_offset_list Got_offset_list* got_next_; }; +// The Local_got_entry_key used to index the GOT offsets for local +// non-TLS symbols, and tp-relative offsets for TLS symbols. + +class Local_got_entry_key +{ + public: + Local_got_entry_key(unsigned int symndx, uint64_t addend) + : symndx_(symndx), addend_(addend) + {} + + // Whether this equals to another Local_got_entry_key. + bool + eq(const Local_got_entry_key& key) const + { + return (this->symndx_ == key.symndx_ && this->addend_ == key.addend_); + } + + // Compute a hash value for this using 64-bit FNV-1a hash. + size_t + hash_value() const + { + uint64_t h = 14695981039346656037ULL; // FNV offset basis. + uint64_t prime = 1099511628211ULL; + h = (h ^ static_cast(this->symndx_)) * prime; + h = (h ^ static_cast(this->addend_)) * prime; + return h; + } + + // Functors for associative containers. + struct equal_to + { + bool + operator()(const Local_got_entry_key& key1, + const Local_got_entry_key& key2) const + { return key1.eq(key2); } + }; + + struct hash + { + size_t + operator()(const Local_got_entry_key& key) const + { return key.hash_value(); } + }; + + private: + // The local symbol index. + unsigned int symndx_; + // The addend. + uint64_t addend_; +}; + // Type for mapping section index to uncompressed size and contents. struct Compressed_section_info { section_size_type size; + elfcpp::Elf_Xword flag; + uint64_t addralign; const unsigned char* contents; }; typedef std::map Compressed_section_map; @@ -380,6 +434,12 @@ class Object is_dynamic() const { return this->is_dynamic_; } + // Return the word size of the object file. + virtual int elfsize() const = 0; + + // Return TRUE if this is a big-endian object file. + virtual bool is_big_endian() const = 0; + // Return whether this object is needed--true if it is a dynamic // object which defines some symbol referenced by a regular object. // We keep the flag here rather than in Dynobj for convenience when @@ -724,6 +784,11 @@ class Object set_as_needed() { this->as_needed_ = true; } + // Clear flag that this object was linked with --as-needed. + void + clear_as_needed() + { this->as_needed_ = false; } + // Return whether this object was linked with --as-needed. bool as_needed() const @@ -744,7 +809,8 @@ class Object bool section_is_compressed(unsigned int shndx, - section_size_type* uncompressed_size) const + section_size_type* uncompressed_size, + elfcpp::Elf_Xword* palign = NULL) const { if (this->compressed_sections_ == NULL) return false; @@ -754,6 +820,8 @@ class Object { if (uncompressed_size != NULL) *uncompressed_size = p->second.size; + if (palign != NULL) + *palign = p->second.addralign; return true; } return false; @@ -764,7 +832,7 @@ class Object // by the caller. const unsigned char* decompressed_section_contents(unsigned int shndx, section_size_type* plen, - bool* is_cached); + bool* is_cached, uint64_t* palign = NULL); // Discard any buffers of decompressed sections. This is done // at the end of the Add_symbols task. @@ -781,6 +849,11 @@ class Object get_incremental_reloc_count(unsigned int symndx) const { return this->do_get_incremental_reloc_count(symndx); } + // Return the output view for section SHNDX. + unsigned char* + get_output_view(unsigned int shndx, section_size_type* plen) const + { return this->do_get_output_view(shndx, plen); } + protected: // Returns NULL for Objects that are not dynamic objects. This method // is overridden in the Dynobj class. @@ -966,6 +1039,11 @@ class Object do_get_incremental_reloc_count(unsigned int) const { gold_unreachable(); } + // Return the output view for a section. + virtual unsigned char* + do_get_output_view(unsigned int, section_size_type*) const + { gold_unreachable(); } + void set_compressed_sections(Compressed_section_map* compressed_sections) { this->compressed_sections_ = compressed_sections; } @@ -1099,21 +1177,43 @@ class Relobj : public Object // GOT_TYPE. bool local_has_got_offset(unsigned int symndx, unsigned int got_type) const - { return this->do_local_has_got_offset(symndx, got_type); } + { return this->do_local_has_got_offset(symndx, got_type, 0); } + + // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset + // of type GOT_TYPE. + bool + local_has_got_offset(unsigned int symndx, unsigned int got_type, + uint64_t addend) const + { return this->do_local_has_got_offset(symndx, got_type, addend); } // Return the GOT offset of type GOT_TYPE of the local symbol // SYMNDX. It is an error to call this if the symbol does not have // a GOT offset of the specified type. unsigned int local_got_offset(unsigned int symndx, unsigned int got_type) const - { return this->do_local_got_offset(symndx, got_type); } + { return this->do_local_got_offset(symndx, got_type, 0); } + + // Return the GOT offset of type GOT_TYPE of the local symbol + // SYMNDX plus ADDEND. It is an error to call this if the symbol + // does not have a GOT offset of the specified type. + unsigned int + local_got_offset(unsigned int symndx, unsigned int got_type, + uint64_t addend) const + { return this->do_local_got_offset(symndx, got_type, addend); } // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX // to GOT_OFFSET. void set_local_got_offset(unsigned int symndx, unsigned int got_type, unsigned int got_offset) - { this->do_set_local_got_offset(symndx, got_type, got_offset); } + { this->do_set_local_got_offset(symndx, got_type, got_offset, 0); } + + // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX + // plus ADDEND to GOT_OFFSET. + void + set_local_got_offset(unsigned int symndx, unsigned int got_type, + unsigned int got_offset, uint64_t addend) + { this->do_set_local_got_offset(symndx, got_type, got_offset, addend); } // Return whether the local symbol SYMNDX is a TLS symbol. bool @@ -1306,19 +1406,21 @@ class Relobj : public Object virtual unsigned int do_local_plt_offset(unsigned int symndx) const = 0; - // Return whether a local symbol has a GOT offset of a given type. + // Return whether a local symbol plus addend has a GOT offset + // of a given type. virtual bool do_local_has_got_offset(unsigned int symndx, - unsigned int got_type) const = 0; + unsigned int got_type, uint64_t addend) const = 0; - // Return the GOT offset of a given type of a local symbol. + // Return the GOT offset of a given type of a local symbol plus addend. virtual unsigned int - do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0; + do_local_got_offset(unsigned int symndx, unsigned int got_type, + uint64_t addend) const = 0; - // Set the GOT offset with a given type for a local symbol. + // Set the GOT offset with a given type for a local symbol plus addend. virtual void do_set_local_got_offset(unsigned int symndx, unsigned int got_type, - unsigned int got_offset) = 0; + unsigned int got_offset, uint64_t addend) = 0; // Return whether local symbol SYMNDX is a TLS symbol. virtual bool @@ -1981,24 +2083,28 @@ class Sized_relobj : public Relobj : convert_types(off)); } - // Return whether the local symbol SYMNDX has a GOT offset of type - // GOT_TYPE. + // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset + // of type GOT_TYPE. bool - do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const + do_local_has_got_offset(unsigned int symndx, unsigned int got_type, + uint64_t addend) const { + Local_got_entry_key key(symndx, addend); Local_got_offsets::const_iterator p = - this->local_got_offsets_.find(symndx); + this->local_got_offsets_.find(key); return (p != this->local_got_offsets_.end() && p->second->get_offset(got_type) != -1U); } // Return the GOT offset of type GOT_TYPE of the local symbol - // SYMNDX. + // SYMNDX plus ADDEND. unsigned int - do_local_got_offset(unsigned int symndx, unsigned int got_type) const + do_local_got_offset(unsigned int symndx, unsigned int got_type, + uint64_t addend) const { + Local_got_entry_key key(symndx, addend); Local_got_offsets::const_iterator p = - this->local_got_offsets_.find(symndx); + this->local_got_offsets_.find(key); gold_assert(p != this->local_got_offsets_.end()); unsigned int off = p->second->get_offset(got_type); gold_assert(off != -1U); @@ -2006,20 +2112,21 @@ class Sized_relobj : public Relobj } // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX - // to GOT_OFFSET. + // plus ADDEND to GOT_OFFSET. void do_set_local_got_offset(unsigned int symndx, unsigned int got_type, - unsigned int got_offset) + unsigned int got_offset, uint64_t addend) { + Local_got_entry_key key(symndx, addend); Local_got_offsets::const_iterator p = - this->local_got_offsets_.find(symndx); + this->local_got_offsets_.find(key); if (p != this->local_got_offsets_.end()) p->second->set_offset(got_type, got_offset); else { Got_offset_list* g = new Got_offset_list(got_type, got_offset); std::pair ins = - this->local_got_offsets_.insert(std::make_pair(symndx, g)); + this->local_got_offsets_.insert(std::make_pair(key, g)); gold_assert(ins.second); } } @@ -2037,10 +2144,12 @@ class Sized_relobj : public Relobj private: // The GOT offsets of local symbols. This map also stores GOT offsets // for tp-relative offsets for TLS symbols. - typedef Unordered_map Local_got_offsets; + typedef Unordered_map Local_got_offsets; // GOT offsets for local non-TLS symbols, and tp-relative offsets - // for TLS symbols, indexed by symbol number. + // for TLS symbols, indexed by local got entry key class. Local_got_offsets local_got_offsets_; // For each input section, the offset of the input section in its // output section. This is INVALID_ADDRESS if the input section requires a @@ -2200,7 +2309,17 @@ class Sized_relobj_file : public Sized_relobj // and return its output address. This is used only for relocations in // debugging sections. Address - map_to_kept_section(unsigned int shndx, bool* found) const; + map_to_kept_section(unsigned int shndx, std::string& section_name, + bool* found) const; + + // Look for a kept section corresponding to the given discarded section, + // and return its object file. + Relobj* + find_kept_section_object(unsigned int shndx, unsigned int* symndx_p) const; + + // Return the name of symbol SYMNDX. + const char* + get_symbol_name(unsigned int symndx); // Compute final local symbol value. R_SYM is the local symbol index. // LV_IN points to a local symbol value containing the input value. @@ -2458,6 +2577,13 @@ class Sized_relobj_file : public Sized_relobj const unsigned char* pshdrs, Output_file* of, Views* pviews); + // Relocate section data for a range of sections. + void + relocate_section_range(const Symbol_table* symtab, const Layout* layout, + const unsigned char* pshdrs, Output_file* of, + Views* pviews, unsigned int start_shndx, + unsigned int end_shndx); + // Adjust this local symbol value. Return false if the symbol // should be discarded from the output file. virtual bool @@ -2469,6 +2595,10 @@ class Sized_relobj_file : public Sized_relobj set_output_local_symbol_count(unsigned int value) { this->output_local_symbol_count_ = value; } + // Return the output view for a section. + unsigned char* + do_get_output_view(unsigned int, section_size_type*) const; + private: // For convenience. typedef Sized_relobj_file This; @@ -2476,17 +2606,22 @@ class Sized_relobj_file : public Sized_relobj static const int shdr_size = elfcpp::Elf_sizes::shdr_size; static const int sym_size = elfcpp::Elf_sizes::sym_size; typedef elfcpp::Shdr Shdr; + typedef elfcpp::Shdr_write Shdr_write; // To keep track of discarded comdat sections, we need to map a member // section index to the object and section index of the corresponding // kept section. struct Kept_comdat_section { - Kept_comdat_section(Relobj* a_object, unsigned int a_shndx) - : object(a_object), shndx(a_shndx) + Kept_comdat_section(uint64_t a_sh_size, Kept_section* a_kept_section, + unsigned int a_symndx, bool a_is_comdat) + : sh_size(a_sh_size), kept_section(a_kept_section), + symndx (a_symndx), is_comdat(a_is_comdat) { } - Relobj* object; - unsigned int shndx; + uint64_t sh_size; // Section size + Kept_section* kept_section; // Kept section info + unsigned int symndx; // Index of key symbol + bool is_comdat; // True if comdat group, false if linkonce }; typedef std::map Kept_comdat_section_table; @@ -2520,8 +2655,8 @@ class Sized_relobj_file : public Sized_relobj // Layout an input section. void layout_section(Layout* layout, unsigned int shndx, const char* name, - const typename This::Shdr& shdr, unsigned int reloc_shndx, - unsigned int reloc_type); + const typename This::Shdr& shdr, unsigned int sh_type, + unsigned int reloc_shndx, unsigned int reloc_type); // Layout an input .eh_frame section. void @@ -2532,6 +2667,10 @@ class Sized_relobj_file : public Sized_relobj unsigned int shndx, const typename This::Shdr&, unsigned int reloc_shndx, unsigned int reloc_type); + // Layout an input .note.gnu.property section. + void + layout_gnu_property_section(Layout* layout, unsigned int shndx); + // Write section data to the output file. Record the views and // sizes in VIEWS for use when relocating. void @@ -2602,7 +2741,8 @@ class Sized_relobj_file : public Sized_relobj unsigned int sh_type, unsigned int shndx, const unsigned char* prelocs, size_t reloc_count, unsigned char* view, section_size_type view_size, - Reloc_symbol_changes** reloc_map); + Reloc_symbol_changes** reloc_map, + const Sized_target* target); template void @@ -2610,7 +2750,8 @@ class Sized_relobj_file : public Sized_relobj unsigned int shndx, const unsigned char* prelocs, size_t reloc_count, unsigned char* view, section_size_type view_size, - Reloc_symbol_changes** reloc_map); + Reloc_symbol_changes** reloc_map, + const Sized_target* target); // Find all functions in a section. void @@ -2629,25 +2770,29 @@ class Sized_relobj_file : public Sized_relobj // Record a mapping from discarded section SHNDX to the corresponding // kept section. void - set_kept_comdat_section(unsigned int shndx, Relobj* kept_object, - unsigned int kept_shndx) + set_kept_comdat_section(unsigned int shndx, bool is_comdat, + unsigned int symndx, uint64_t sh_size, + Kept_section* kept_section) { - Kept_comdat_section kept(kept_object, kept_shndx); + Kept_comdat_section kept(sh_size, kept_section, symndx, is_comdat); this->kept_comdat_sections_.insert(std::make_pair(shndx, kept)); } // Find the kept section corresponding to the discarded section // SHNDX. Return true if found. bool - get_kept_comdat_section(unsigned int shndx, Relobj** kept_object, - unsigned int* kept_shndx) const + get_kept_comdat_section(unsigned int shndx, bool* is_comdat, + unsigned int *symndx, uint64_t* sh_size, + Kept_section** kept_section) const { typename Kept_comdat_section_table::const_iterator p = this->kept_comdat_sections_.find(shndx); if (p == this->kept_comdat_sections_.end()) return false; - *kept_object = p->second.object; - *kept_shndx = p->second.shndx; + *is_comdat = p->second.is_comdat; + *symndx = p->second.symndx; + *sh_size = p->second.sh_size; + *kept_section = p->second.kept_section; return true; } @@ -2681,15 +2826,18 @@ class Sized_relobj_file : public Sized_relobj { static const int shdr_size = elfcpp::Elf_sizes::shdr_size; Deferred_layout(unsigned int shndx, const char* name, + unsigned int sh_type, const unsigned char* pshdr, unsigned int reloc_shndx, unsigned int reloc_type) - : shndx_(shndx), name_(name), reloc_shndx_(reloc_shndx), + : name_(name), shndx_(shndx), reloc_shndx_(reloc_shndx), reloc_type_(reloc_type) { + typename This::Shdr_write shdr(this->shdr_data_); memcpy(this->shdr_data_, pshdr, shdr_size); + shdr.put_sh_type(sh_type); } - unsigned int shndx_; std::string name_; + unsigned int shndx_; unsigned int reloc_shndx_; unsigned int reloc_type_; unsigned char shdr_data_[shdr_size]; @@ -2725,9 +2873,6 @@ class Sized_relobj_file : public Sized_relobj Kept_comdat_section_table kept_comdat_sections_; // Whether this object has a GNU style .eh_frame section. bool has_eh_frame_; - // If this object has a GNU style .eh_frame section that is discarded in - // output, record the index here. Otherwise it is -1U. - unsigned int discarded_eh_frame_shndx_; // True if the layout of this object was deferred, waiting for plugin // replacement files. bool is_deferred_layout_; @@ -2735,6 +2880,8 @@ class Sized_relobj_file : public Sized_relobj std::vector deferred_layout_; // The list of relocation sections whose layout was deferred. std::vector deferred_layout_relocs_; + // Pointer to the list of output views; valid only during do_relocate(). + const Views* output_views_; }; // A class to manage the list of all objects. @@ -2829,7 +2976,7 @@ class Input_objects // The list of dynamic objects included in the link. Dynobj_list dynobj_list_; // SONAMEs that we have seen. - Unordered_set sonames_; + Unordered_map sonames_; // Manage cross-references if requested. Cref* cref_; }; @@ -2850,6 +2997,8 @@ struct Relocate_info unsigned int reloc_shndx; // Section header of relocation section. const unsigned char* reloc_shdr; + // Info about how relocs should be handled + Relocatable_relocs* rr; // Section index of section being relocated. unsigned int data_shndx; // Section header of data section. @@ -2863,11 +3012,11 @@ struct Relocate_info // This is used to represent a section in an object and is used as the // key type for various section maps. -typedef std::pair Section_id; +typedef std::pair Section_id; // This is similar to Section_id but is used when the section // pointers are const. -typedef std::pair Const_section_id; +typedef std::pair Const_section_id; // The hash value is based on the address of an object in memory during // linking. It is okay to use this for looking up sections but never use