X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Fmips.cc;h=65572d8884f6d5ef0bbcd696d15211475f15478f;hb=abdb711e0855f0597a96db0486b598144b788212;hp=42ec64b7be63fad2bc2d0909721a59ceea978bbc;hpb=b52717c0e104eb603e8189c3c0d3658ef5d903f5;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/mips.cc b/gold/mips.cc index 42ec64b7be..65572d8884 100644 --- a/gold/mips.cc +++ b/gold/mips.cc @@ -1,6 +1,6 @@ // mips.cc -- mips target support for gold. -// Copyright (C) 2011-2016 Free Software Foundation, Inc. +// Copyright (C) 2011-2019 Free Software Foundation, Inc. // Written by Sasa Stankovic // and Aleksandar Simeonov . // This file contains borrowed and adapted code from bfd/elfxx-mips.c. @@ -63,6 +63,9 @@ class Target_mips; template class Mips_output_section_reginfo; +template +class Mips_output_section_options; + template class Mips_output_data_la25_stub; @@ -178,6 +181,8 @@ relocation_needs_la25_stub(Mips_relobj* object, { case elfcpp::R_MIPS_26: case elfcpp::R_MIPS_PC16: + case elfcpp::R_MIPS_PC21_S2: + case elfcpp::R_MIPS_PC26_S2: case elfcpp::R_MICROMIPS_26_S1: case elfcpp::R_MICROMIPS_PC7_S1: case elfcpp::R_MICROMIPS_PC10_S1: @@ -224,7 +229,8 @@ hi16_reloc(int r_type) { return (r_type == elfcpp::R_MIPS_HI16 || r_type == elfcpp::R_MIPS16_HI16 - || r_type == elfcpp::R_MICROMIPS_HI16); + || r_type == elfcpp::R_MICROMIPS_HI16 + || r_type == elfcpp::R_MIPS_PCHI16); } static inline bool @@ -232,7 +238,8 @@ lo16_reloc(int r_type) { return (r_type == elfcpp::R_MIPS_LO16 || r_type == elfcpp::R_MIPS16_LO16 - || r_type == elfcpp::R_MICROMIPS_LO16); + || r_type == elfcpp::R_MICROMIPS_LO16 + || r_type == elfcpp::R_MIPS_PCLO16); } static inline bool @@ -404,6 +411,8 @@ is_matching_lo16_reloc(unsigned int high_reloc, unsigned int lo16_reloc) case elfcpp::R_MIPS_HI16: case elfcpp::R_MIPS_GOT16: return lo16_reloc == elfcpp::R_MIPS_LO16; + case elfcpp::R_MIPS_PCHI16: + return lo16_reloc == elfcpp::R_MIPS_PCLO16; case elfcpp::R_MIPS16_HI16: case elfcpp::R_MIPS16_GOT16: return lo16_reloc == elfcpp::R_MIPS16_LO16; @@ -465,22 +474,24 @@ class Mips_got_entry ? this->d.object->name().c_str() : this->d.sym->name()); size_t addend = this->addend_; - return name_hash_value ^ this->symndx_ ^ addend; + return name_hash_value ^ this->symndx_ ^ (addend << 16); } // Return whether this entry is equal to OTHER. bool equals(Mips_got_entry* other) const { + if (this->symndx_ != other->symndx_ + || this->tls_type_ != other->tls_type_) + return false; + if (this->tls_type_ == GOT_TLS_LDM) return true; - return ((this->tls_type_ == other->tls_type_) - && (this->symndx_ == other->symndx_) - && ((this->symndx_ != -1U) - ? (this->d.object == other->d.object) - : (this->d.sym == other->d.sym)) - && (this->addend_ == other->addend_)); + return (((this->symndx_ != -1U) + ? (this->d.object == other->d.object) + : (this->d.sym == other->d.sym)) + && (this->addend_ == other->addend_)); } // Return input object that needs this GOT entry. @@ -620,11 +631,11 @@ struct Got_page_range struct Got_page_entry { Got_page_entry() - : object(NULL), symndx(-1U), ranges(NULL), num_pages(0) + : object(NULL), symndx(-1U), ranges(NULL) { } Got_page_entry(Object* object_, unsigned int symndx_) - : object(object_), symndx(symndx_), ranges(NULL), num_pages(0) + : object(object_), symndx(symndx_), ranges(NULL) { } // The input object that needs the GOT page entry. @@ -633,8 +644,6 @@ struct Got_page_entry unsigned int symndx; // The ranges for this page entry. Got_page_range* ranges; - // The maximum number of page entries needed for RANGES. - unsigned int num_pages; }; // Hash for Got_page_entry. @@ -764,7 +773,7 @@ class Mips_got_info // Add FROM's GOT page entries. void - add_got_page_entries(Mips_got_info* from); + add_got_page_count(Mips_got_info* from); // Return GOT size. unsigned int @@ -917,7 +926,7 @@ class Mips_got_info Global_got_entry_set global_got_symbols_; // A hash table holding GOT entries. Got_entry_set got_entries_; - // A hash table of GOT page entries. + // A hash table of GOT page entries (only used in master GOT). Got_page_entry_set got_page_entries_; // The offset of first GOT page entry for this GOT. unsigned int got_page_offset_start_; @@ -1583,10 +1592,11 @@ class Mips_relobj : public Sized_relobj_file local_symbol_is_micromips_(), mips16_stub_sections_(), local_non_16bit_calls_(), local_16bit_calls_(), local_mips16_fn_stubs_(), local_mips16_call_stubs_(), gp_(0), has_reginfo_section_(false), - got_info_(NULL), section_is_mips16_fn_stub_(), - section_is_mips16_call_stub_(), section_is_mips16_call_fp_stub_(), - pdr_shndx_(-1U), attributes_section_data_(NULL), abiflags_(NULL), - gprmask_(0), cprmask1_(0), cprmask2_(0), cprmask3_(0), cprmask4_(0) + merge_processor_specific_data_(true), got_info_(NULL), + section_is_mips16_fn_stub_(), section_is_mips16_call_stub_(), + section_is_mips16_call_fp_stub_(), pdr_shndx_(-1U), + attributes_section_data_(NULL), abiflags_(NULL), gprmask_(0), + cprmask1_(0), cprmask2_(0), cprmask3_(0), cprmask4_(0) { this->is_pic_ = (ehdr.get_e_flags() & elfcpp::EF_MIPS_PIC) != 0; this->is_n32_ = elfcpp::abi_n32(ehdr.get_e_flags()); @@ -1827,6 +1837,11 @@ class Mips_relobj : public Sized_relobj_file has_reginfo_section() const { return this->has_reginfo_section_; } + // Return whether we want to merge processor-specific data. + bool + merge_processor_specific_data() const + { return this->merge_processor_specific_data_; } + // Return gprmask from the .reginfo section of this object. Valtype gprmask() const @@ -1917,6 +1932,8 @@ class Mips_relobj : public Sized_relobj_file bool is_n32_ : 1; // Whether the object contains a .reginfo section. bool has_reginfo_section_ : 1; + // Whether we merge processor-specific data of this object to output. + bool merge_processor_specific_data_ : 1; // The Mips_got_info for this object. Mips_got_info* got_info_; @@ -2469,7 +2486,7 @@ class Mips_output_data_plt : public Output_section_data add_entry(Mips_symbol* gsym, unsigned int r_type); // Return the .rel.plt section data. - const Reloc_section* + Reloc_section* rel_plt() const { return this->rel_; } @@ -2546,6 +2563,7 @@ class Mips_output_data_plt : public Output_section_data // Template for subsequent PLT entries. static const uint32_t plt_entry[]; + static const uint32_t plt_entry_r6[]; static const uint32_t plt_entry_mips16_o32[]; static const uint32_t plt_entry_micromips_o32[]; static const uint32_t plt_entry_micromips32_o32[]; @@ -2814,6 +2832,31 @@ class Mips_output_section_reginfo : public Output_section_data Valtype cprmask4_; }; +// This class handles .MIPS.options output section. + +template +class Mips_output_section_options : public Output_section +{ + public: + Mips_output_section_options(const char* name, elfcpp::Elf_Word type, + elfcpp::Elf_Xword flags, + Target_mips* target) + : Output_section(name, type, flags), target_(target) + { + // After the input sections are written, we only need to update + // ri_gp_value field of ODK_REGINFO entries. + this->set_after_input_sections(); + } + + protected: + // Write out option section. + void + do_write(Output_file* of); + + private: + Target_mips* target_; +}; + // This class handles .MIPS.abiflags output section. template @@ -2919,8 +2962,7 @@ symbol_refs_local(const Symbol* sym, bool has_dynsym_entry, // If we don't have a definition in a regular file, then we can't // resolve locally. The sym is either undefined or dynamic. - if (sym->source() != Symbol::FROM_OBJECT || sym->object()->is_dynamic() - || sym->is_undefined()) + if (sym->is_from_dynobj() || sym->is_undefined()) return false; // Forced local symbols resolve locally. @@ -3285,10 +3327,10 @@ class Target_mips : public Sized_target public: Target_mips(const Target::Target_info* info = &mips_info) : Sized_target(info), got_(NULL), gp_(NULL), plt_(NULL), - got_plt_(NULL), rel_dyn_(NULL), copy_relocs_(), dyn_relocs_(), - la25_stub_(NULL), mips_mach_extensions_(), mips_stubs_(NULL), - attributes_section_data_(NULL), abiflags_(NULL), mach_(0), layout_(NULL), - got16_addends_(), has_abiflags_section_(false), + got_plt_(NULL), rel_dyn_(NULL), rld_map_(NULL), copy_relocs_(), + dyn_relocs_(), la25_stub_(NULL), mips_mach_extensions_(), + mips_stubs_(NULL), attributes_section_data_(NULL), abiflags_(NULL), + mach_(0), layout_(NULL), got16_addends_(), has_abiflags_section_(false), entry_symbol_is_compressed_(false), insn32_(false) { this->add_machine_extensions(); @@ -3575,6 +3617,15 @@ class Target_mips : public Sized_target return elfcpp::abi_n32(this->processor_specific_flags()); } + // Whether the output uses R6 ISA. This is valid only after + // merge_obj_e_flags() is called. + bool + is_output_r6() const + { + gold_assert(this->are_processor_specific_flags_set()); + return elfcpp::r6_isa(this->processor_specific_flags()); + } + // Whether the output uses N64 ABI. bool is_output_n64() const @@ -3620,6 +3671,18 @@ class Target_mips : public Sized_target const elfcpp::Ehdr&) { gold_unreachable(); } + // Make an output section. + Output_section* + do_make_output_section(const char* name, elfcpp::Elf_Word type, + elfcpp::Elf_Xword flags) + { + if (type == elfcpp::SHT_MIPS_OPTIONS) + return new Mips_output_section_options(name, type, + flags, this); + else + return new Output_section(name, type, flags); + } + // Adjust ELF file header. void do_adjust_elf_header(unsigned char* view, int len); @@ -3802,6 +3865,7 @@ class Target_mips : public Sized_target { public: Relocate() + : calculated_value_(0), calculate_only_(false) { } ~Relocate() @@ -3821,6 +3885,12 @@ class Target_mips : public Sized_target Target_mips*, Output_section*, size_t, const unsigned char*, const Sized_symbol*, const Symbol_value*, unsigned char*, Mips_address, section_size_type); + + private: + // Result of the relocation. + Valtype calculated_value_; + // Whether we have to calculate relocation instead of applying it. + bool calculate_only_; }; // This POD class holds the dynamic relocations that should be emitted instead @@ -3912,7 +3982,9 @@ class Target_mips : public Sized_target mach_mips5 = 5, mach_mips_loongson_2e = 3001, mach_mips_loongson_2f = 3002, - mach_mips_loongson_3a = 3003, + mach_mips_gs464 = 3003, + mach_mips_gs464e = 3004, + mach_mips_gs264e = 3005, mach_mips_sb1 = 12310201, // octal 'SB', 01 mach_mips_octeon = 6501, mach_mips_octeonp = 6601, @@ -3923,10 +3995,12 @@ class Target_mips : public Sized_target mach_mipsisa32r2 = 33, mach_mipsisa32r3 = 34, mach_mipsisa32r5 = 36, + mach_mipsisa32r6 = 37, mach_mipsisa64 = 64, mach_mipsisa64r2 = 65, mach_mipsisa64r3 = 66, mach_mipsisa64r5 = 68, + mach_mipsisa64r6 = 69, mach_mips_micromips = 96 }; @@ -4076,7 +4150,9 @@ class Target_mips : public Sized_target this->add_extension(mach_mips_octeon2, mach_mips_octeonp); this->add_extension(mach_mips_octeonp, mach_mips_octeon); this->add_extension(mach_mips_octeon, mach_mipsisa64r2); - this->add_extension(mach_mips_loongson_3a, mach_mipsisa64r2); + this->add_extension(mach_mips_gs264e, mach_mips_gs464e); + this->add_extension(mach_mips_gs464e, mach_mips_gs464); + this->add_extension(mach_mips_gs464, mach_mipsisa64r2); // MIPS64 extensions. this->add_extension(mach_mipsisa64r2, mach_mipsisa64); @@ -4163,6 +4239,8 @@ class Target_mips : public Sized_target Output_data_space* got_plt_; // The dynamic reloc section. Reloc_section* rel_dyn_; + // The .rld_map section. + Output_data_zero_fill* rld_map_; // Relocs saved to avoid a COPY reloc. Mips_copy_relocs copy_relocs_; @@ -4237,9 +4315,10 @@ class Mips_relocate_functions : public Relocate_functions public: typedef enum { - STATUS_OKAY, // No error during relocation. - STATUS_OVERFLOW, // Relocation overflow. - STATUS_BAD_RELOC // Relocation cannot be applied. + STATUS_OKAY, // No error during relocation. + STATUS_OVERFLOW, // Relocation overflow. + STATUS_BAD_RELOC, // Relocation cannot be applied. + STATUS_PCREL_UNALIGNED // Unaligned PC-relative relocation. } Status; private: @@ -4248,6 +4327,7 @@ class Mips_relocate_functions : public Relocate_functions static typename std::list > hi16_relocs; static typename std::list > got16_relocs; + static typename std::list > pchi16_relocs; template static inline typename This::Status @@ -4478,8 +4558,7 @@ class Mips_relocate_functions : public Relocate_functions Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); // Try converting J(AL)R to B(AL), if the target is in range. - if (!parameters->options().relocatable() - && r_type == elfcpp::R_MIPS_JALR + if (r_type == elfcpp::R_MIPS_JALR && !cross_mode_jump && ((jalr_to_bal && val == 0x0320f809) // jalr t9 || (jr_to_b && val == 0x03200008))) // jr t9 @@ -4570,15 +4649,9 @@ class Mips_relocate_functions : public Relocate_functions } x = psymval->value(object, x) >> shift; - if (!calculate_only && !local && !gsym->is_weak_undefined()) - { - if ((x >> 26) != ((address + 4) >> (26 + shift))) - { - gold_error(_("relocation truncated to fit: %u against '%s'"), - r_type, gsym->name()); - return This::STATUS_OVERFLOW; - } - } + if (!calculate_only && !local && !gsym->is_weak_undefined() + && ((x >> 26) != ((address + 4) >> (26 + shift)))) + return This::STATUS_OVERFLOW; val = Bits<32>::bit_select32(val, x, 0x03ffffff); @@ -4670,9 +4743,220 @@ class Mips_relocate_functions : public Relocate_functions else elfcpp::Swap<32, big_endian>::writeval(wv, val); + if (psymval->value(object, addend) & 3) + return This::STATUS_PCREL_UNALIGNED; + return check_overflow<18>(x); } + // R_MIPS_PC21_S2 + static inline typename This::Status + relpc21(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address address, + Mips_address addend_a, bool extract_addend, bool calculate_only, + Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + + Valtype addend = (extract_addend + ? Bits<23>::sign_extend32((val & 0x1fffff) << 2) + : addend_a); + + Valtype x = psymval->value(object, addend) - address; + val = Bits<21>::bit_select32(val, x >> 2, 0x1fffff); + + if (calculate_only) + { + *calculated_value = x >> 2; + return This::STATUS_OKAY; + } + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + if (psymval->value(object, addend) & 3) + return This::STATUS_PCREL_UNALIGNED; + + return check_overflow<23>(x); + } + + // R_MIPS_PC26_S2 + static inline typename This::Status + relpc26(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address address, + Mips_address addend_a, bool extract_addend, bool calculate_only, + Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + + Valtype addend = (extract_addend + ? Bits<28>::sign_extend32((val & 0x3ffffff) << 2) + : addend_a); + + Valtype x = psymval->value(object, addend) - address; + val = Bits<26>::bit_select32(val, x >> 2, 0x3ffffff); + + if (calculate_only) + { + *calculated_value = x >> 2; + return This::STATUS_OKAY; + } + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + if (psymval->value(object, addend) & 3) + return This::STATUS_PCREL_UNALIGNED; + + return check_overflow<28>(x); + } + + // R_MIPS_PC18_S3 + static inline typename This::Status + relpc18(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address address, + Mips_address addend_a, bool extract_addend, bool calculate_only, + Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + + Valtype addend = (extract_addend + ? Bits<21>::sign_extend32((val & 0x3ffff) << 3) + : addend_a); + + Valtype x = psymval->value(object, addend) - ((address | 7) ^ 7); + val = Bits<18>::bit_select32(val, x >> 3, 0x3ffff); + + if (calculate_only) + { + *calculated_value = x >> 3; + return This::STATUS_OKAY; + } + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + if (psymval->value(object, addend) & 7) + return This::STATUS_PCREL_UNALIGNED; + + return check_overflow<21>(x); + } + + // R_MIPS_PC19_S2 + static inline typename This::Status + relpc19(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address address, + Mips_address addend_a, bool extract_addend, bool calculate_only, + Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + + Valtype addend = (extract_addend + ? Bits<21>::sign_extend32((val & 0x7ffff) << 2) + : addend_a); + + Valtype x = psymval->value(object, addend) - address; + val = Bits<19>::bit_select32(val, x >> 2, 0x7ffff); + + if (calculate_only) + { + *calculated_value = x >> 2; + return This::STATUS_OKAY; + } + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + if (psymval->value(object, addend) & 3) + return This::STATUS_PCREL_UNALIGNED; + + return check_overflow<21>(x); + } + + // R_MIPS_PCHI16 + static inline typename This::Status + relpchi16(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address addend, + Mips_address address, unsigned int r_sym, bool extract_addend) + { + // Record the relocation. It will be resolved when we find pclo16 part. + pchi16_relocs.push_back(reloc_high(view, object, psymval, + addend, 0, r_sym, extract_addend, address)); + return This::STATUS_OKAY; + } + + // R_MIPS_PCHI16 + static inline typename This::Status + do_relpchi16(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address addend_hi, + Mips_address address, bool extract_addend, Valtype32 addend_lo, + bool calculate_only, Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + + Valtype addend = (extract_addend ? ((val & 0xffff) << 16) + addend_lo + : addend_hi); + + Valtype value = psymval->value(object, addend) - address; + Valtype x = ((value + 0x8000) >> 16) & 0xffff; + val = Bits<32>::bit_select32(val, x, 0xffff); + + if (calculate_only) + *calculated_value = x; + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + return This::STATUS_OKAY; + } + + // R_MIPS_PCLO16 + static inline typename This::Status + relpclo16(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address addend_a, + bool extract_addend, Mips_address address, unsigned int r_sym, + unsigned int rel_type, bool calculate_only, + Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + + Valtype addend = (extract_addend ? Bits<16>::sign_extend32(val & 0xffff) + : addend_a); + + if (rel_type == elfcpp::SHT_REL) + { + // Resolve pending R_MIPS_PCHI16 relocations. + typename std::list >::iterator it = + pchi16_relocs.begin(); + while (it != pchi16_relocs.end()) + { + reloc_high pchi16 = *it; + if (pchi16.r_sym == r_sym) + { + do_relpchi16(pchi16.view, pchi16.object, pchi16.psymval, + pchi16.addend, pchi16.address, + pchi16.extract_addend, addend, calculate_only, + calculated_value); + it = pchi16_relocs.erase(it); + } + else + ++it; + } + } + + // Resolve R_MIPS_PCLO16 relocation. + Valtype x = psymval->value(object, addend) - address; + val = Bits<32>::bit_select32(val, x, 0xffff); + + if (calculate_only) + *calculated_value = x; + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + return This::STATUS_OKAY; + } + // R_MICROMIPS_PC7_S1 static inline typename This::Status relmicromips_pc7_s1(unsigned char* view, @@ -5346,6 +5630,52 @@ class Mips_relocate_functions : public Relocate_functions return This::STATUS_OKAY; } + // R_MIPS_HIGHER, R_MICROMIPS_HIGHER + static inline typename This::Status + relhigher(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address addend_a, + bool extract_addend, bool calculate_only, Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + Valtype addend = (extract_addend ? Bits<16>::sign_extend32(val & 0xffff) + : addend_a); + + Valtype x = psymval->value(object, addend); + x = ((x + (uint64_t) 0x80008000) >> 32) & 0xffff; + val = Bits<32>::bit_select32(val, x, 0xffff); + + if (calculate_only) + *calculated_value = x; + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + return This::STATUS_OKAY; + } + + // R_MIPS_HIGHEST, R_MICROMIPS_HIGHEST + static inline typename This::Status + relhighest(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address addend_a, + bool extract_addend, bool calculate_only, + Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + Valtype addend = (extract_addend ? Bits<16>::sign_extend32(val & 0xffff) + : addend_a); + + Valtype x = psymval->value(object, addend); + x = ((x + (uint64_t) 0x800080008000llu) >> 48) & 0xffff; + val = Bits<32>::bit_select32(val, x, 0xffff); + + if (calculate_only) + *calculated_value = x; + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + return This::STATUS_OKAY; + } }; template @@ -5356,6 +5686,10 @@ template typename std::list > Mips_relocate_functions::got16_relocs; +template +typename std::list > + Mips_relocate_functions::pchi16_relocs; + // Mips_got_info methods. // Reserve GOT entry for a GOT relocation of type R_TYPE against symbol @@ -5390,7 +5724,7 @@ Mips_got_info::record_global_got_symbol( mips_sym->set_got_not_only_for_calls(); // A global symbol in the GOT must also be in the dynamic symbol table. - if (!mips_sym->needs_dynsym_entry()) + if (!mips_sym->needs_dynsym_entry() && !mips_sym->is_forced_local()) { switch (mips_sym->visibility()) { @@ -5462,14 +5796,8 @@ Mips_got_info::record_got_page_entry( else this->got_page_entries_.insert(entry); - // Add the same entry to the OBJECT's GOT. - Got_page_entry* entry2 = NULL; + // Get the object's GOT, but we don't need to insert an entry here. Mips_got_info* g2 = object->get_or_create_got_info(); - if (g2->got_page_entries_.find(entry) == g2->got_page_entries_.end()) - { - entry2 = new Got_page_entry(*entry); - g2->got_page_entries_.insert(entry2); - } // Skip over ranges whose maximum extent cannot share a page entry // with ADDEND. @@ -5489,9 +5817,6 @@ Mips_got_info::record_got_page_entry( range->max_addend = addend; *range_ptr = range; - ++entry->num_pages; - if (entry2 != NULL) - ++entry2->num_pages; ++this->page_gotno_; ++g2->page_gotno_; return; @@ -5519,9 +5844,6 @@ Mips_got_info::record_got_page_entry( new_pages = range->get_max_pages(); if (old_pages != new_pages) { - entry->num_pages += new_pages - old_pages; - if (entry2 != NULL) - entry2->num_pages += new_pages - old_pages; this->page_gotno_ += new_pages - old_pages; g2->page_gotno_ += new_pages - old_pages; } @@ -6021,22 +6343,10 @@ Mips_got_info::add_got_entries( template void -Mips_got_info::add_got_page_entries( +Mips_got_info::add_got_page_count( Mips_got_info* from) { - for (typename Got_page_entry_set::iterator - p = from->got_page_entries_.begin(); - p != from->got_page_entries_.end(); - ++p) - { - Got_page_entry* entry = *p; - if (this->got_page_entries_.find(entry) == this->got_page_entries_.end()) - { - Got_page_entry* entry2 = new Got_page_entry(*entry); - this->got_page_entries_.insert(entry2); - this->page_gotno_ += entry->num_pages; - } - } + this->page_gotno_ += from->page_gotno_; } // Mips_output_data_got methods. @@ -6237,7 +6547,7 @@ Mips_output_data_got::merge_got_with( // Transfer the object's GOT information from FROM to TO. to->add_got_entries(from); - to->add_got_page_entries(from); + to->add_got_page_count(from); // Record that OBJECT should use output GOT TO. object->set_got_info(to); @@ -6496,6 +6806,16 @@ Mips_relobj::do_read_symbols(Read_symbols_data* sd) // Call parent class to read symbol information. this->base_read_symbols(sd); + // If this input file is a binary file, it has no processor + // specific data. + Input_file::Format format = this->input_file()->format(); + if (format != Input_file::FORMAT_ELF) + { + gold_assert(format == Input_file::FORMAT_BINARY); + this->merge_processor_specific_data_ = false; + return; + } + // Read processor-specific flags in ELF file header. const unsigned char* pehdr = this->get_view(elfcpp::file_header_offset, elfcpp::Elf_sizes::ehdr_size, @@ -6515,10 +6835,27 @@ Mips_relobj::do_read_symbols(Read_symbols_data* sd) const size_t shdr_size = elfcpp::Elf_sizes::shdr_size; const unsigned char* pshdrs = sd->section_headers->data(); const unsigned char* ps = pshdrs + shdr_size; + bool must_merge_processor_specific_data = false; for (unsigned int i = 1; i < this->shnum(); ++i, ps += shdr_size) { elfcpp::Shdr shdr(ps); + // Sometimes an object has no contents except the section name string + // table and an empty symbol table with the undefined symbol. We + // don't want to merge processor-specific data from such an object. + if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB) + { + // Symbol table is not empty. + const typename elfcpp::Elf_types::Elf_WXword sym_size = + elfcpp::Elf_sizes::sym_size; + if (shdr.get_sh_size() > sym_size) + must_merge_processor_specific_data = true; + } + else if (shdr.get_sh_type() != elfcpp::SHT_STRTAB) + // If this is neither an empty symbol table nor a string table, + // be conservative. + must_merge_processor_specific_data = true; + if (shdr.get_sh_type() == elfcpp::SHT_MIPS_REGINFO) { this->has_reginfo_section_ = true; @@ -6691,6 +7028,10 @@ Mips_relobj::do_read_symbols(Read_symbols_data* sd) this->pdr_shndx_ = i; } } + + // This is rare. + if (!must_merge_processor_specific_data) + this->merge_processor_specific_data_ = false; } // Discard MIPS16 stub secions that are not needed. @@ -7015,6 +7356,16 @@ const uint32_t Mips_output_data_plt::plt_entry[] = 0x25f80000 // addiu $24, $15, %lo(.got.plt entry) }; +// The format of subsequent R6 PLT entries. +template +const uint32_t Mips_output_data_plt::plt_entry_r6[] = +{ + 0x3c0f0000, // lui $15, %hi(.got.plt entry) + 0x01f90000, // l[wd] $25, %lo(.got.plt entry)($15) + 0x03200009, // jr $25 + 0x25f80000 // addiu $24, $15, %lo(.got.plt entry) +}; + // The format of subsequent MIPS16 o32 PLT entries. We use v1 ($3) as a // temporary because t8 ($24) and t9 ($25) are not directly addressable. // Note that this differs from the GNU ld which uses both v0 ($2) and v1 ($3). @@ -7298,14 +7649,17 @@ Mips_output_data_plt::do_write(Output_file* of) uint64_t load = this->target_->is_output_n64() ? 0xdc000000 : 0x8c000000; + const uint32_t* entry = this->target_->is_output_r6() ? plt_entry_r6 + : plt_entry; + // Fill in the PLT entry itself. elfcpp::Swap<32, big_endian>::writeval(pov, - plt_entry[0] | gotplt_entry_addr_hi); + entry[0] | gotplt_entry_addr_hi); elfcpp::Swap<32, big_endian>::writeval(pov + 4, - plt_entry[1] | gotplt_entry_addr_lo | load); - elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_entry[2]); + entry[1] | gotplt_entry_addr_lo | load); + elfcpp::Swap<32, big_endian>::writeval(pov + 8, entry[2]); elfcpp::Swap<32, big_endian>::writeval(pov + 12, - plt_entry[3] | gotplt_entry_addr_lo); + entry[3] | gotplt_entry_addr_lo); pov += 16; } @@ -7888,6 +8242,44 @@ Mips_output_section_reginfo::do_write(Output_file* of) of->write_output_view(offset, data_size, view); } +// Mips_output_section_options methods. + +template +void +Mips_output_section_options::do_write(Output_file* of) +{ + off_t offset = this->offset(); + const section_size_type oview_size = + convert_to_section_size_type(this->data_size()); + unsigned char* view = of->get_output_view(offset, oview_size); + const unsigned char* end = view + oview_size; + + while (view + 8 <= end) + { + unsigned char kind = elfcpp::Swap<8, big_endian>::readval(view); + unsigned char sz = elfcpp::Swap<8, big_endian>::readval(view + 1); + if (sz < 8) + { + gold_error(_("Warning: bad `%s' option size %u smaller " + "than its header in output section"), + this->name(), sz); + break; + } + + // Only update ri_gp_value (GP register value) field of ODK_REGINFO entry. + if (this->target_->is_output_n64() && kind == elfcpp::ODK_REGINFO) + elfcpp::Swap::writeval(view + 32, + this->target_->gp_value()); + else if (kind == elfcpp::ODK_REGINFO) + elfcpp::Swap::writeval(view + 28, + this->target_->gp_value()); + + view += sz; + } + + of->write_output_view(offset, oview_size, view); +} + // Mips_output_section_abiflags methods. template @@ -8082,7 +8474,7 @@ Target_mips::got_section(Symbol_table* symtab, this->got_, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_GLOBAL, - elfcpp::STV_DEFAULT, 0, + elfcpp::STV_HIDDEN, 0, false, false); } @@ -8095,53 +8487,30 @@ template void Target_mips::set_gp(Layout* layout, Symbol_table* symtab) { - if (this->gp_ != NULL) - return; + gold_assert(this->gp_ == NULL); + + Sized_symbol* gp = + static_cast*>(symtab->lookup("_gp")); - Output_data* section = layout->find_output_section(".got"); - if (section == NULL) + // Set _gp symbol if the linker script hasn't created it. + if (gp == NULL || gp->source() != Symbol::IS_CONSTANT) { // If there is no .got section, gp should be based on .sdata. - // TODO(sasa): This is probably not needed. This was needed for older - // MIPS architectures which accessed both GOT and .sdata section using - // gp-relative addressing. Modern Mips Linux ELF architectures don't - // access .sdata using gp-relative addressing. - for (Layout::Section_list::const_iterator - p = layout->section_list().begin(); - p != layout->section_list().end(); - ++p) - { - if (strcmp((*p)->name(), ".sdata") == 0) - { - section = *p; - break; - } - } - } + Output_data* gp_section = (this->got_ != NULL + ? this->got_->output_section() + : layout->find_output_section(".sdata")); - Sized_symbol* gp = - static_cast*>(symtab->lookup("_gp")); - if (gp != NULL) - { - if (gp->source() != Symbol::IS_CONSTANT && section != NULL) - gp->init_output_data(gp->name(), NULL, section, MIPS_GP_OFFSET, 0, - elfcpp::STT_OBJECT, - elfcpp::STB_GLOBAL, - elfcpp::STV_DEFAULT, 0, - false, false); - this->gp_ = gp; - } - else if (section != NULL) - { - gp = static_cast*>(symtab->define_in_output_data( - "_gp", NULL, Symbol_table::PREDEFINED, - section, MIPS_GP_OFFSET, 0, - elfcpp::STT_OBJECT, - elfcpp::STB_GLOBAL, - elfcpp::STV_DEFAULT, - 0, false, false)); - this->gp_ = gp; + if (gp_section != NULL) + gp = static_cast*>(symtab->define_in_output_data( + "_gp", NULL, Symbol_table::PREDEFINED, + gp_section, MIPS_GP_OFFSET, 0, + elfcpp::STT_NOTYPE, + elfcpp::STB_LOCAL, + elfcpp::STV_DEFAULT, + 0, false, false)); } + + this->gp_ = gp; } // Set the dynamic symbol indexes. INDEX is the index of the first @@ -8271,6 +8640,10 @@ Target_mips::make_plt_entry(Symbol_table* symtab, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR), this->plt_, ORDER_PLT, false); + + // Make the sh_info field of .rel.plt point to .plt. + Output_section* rel_plt_os = this->plt_->rel_plt()->output_section(); + rel_plt_os->set_info_section(this->plt_->output_section()); } this->plt_->add_entry(gsym, r_type); @@ -8439,7 +8812,8 @@ Target_mips::mips_32bit_flags(elfcpp::Elf_Word flags) || (flags & elfcpp::EF_MIPS_ARCH) == elfcpp::E_MIPS_ARCH_1 || (flags & elfcpp::EF_MIPS_ARCH) == elfcpp::E_MIPS_ARCH_2 || (flags & elfcpp::EF_MIPS_ARCH) == elfcpp::E_MIPS_ARCH_32 - || (flags & elfcpp::EF_MIPS_ARCH) == elfcpp::E_MIPS_ARCH_32R2); + || (flags & elfcpp::EF_MIPS_ARCH) == elfcpp::E_MIPS_ARCH_32R2 + || (flags & elfcpp::EF_MIPS_ARCH) == elfcpp::E_MIPS_ARCH_32R6); } // Return the MACH for a MIPS e_flags value. @@ -8488,8 +8862,14 @@ Target_mips::elf_mips_mach(elfcpp::Elf_Word flags) case elfcpp::E_MIPS_MACH_LS2F: return mach_mips_loongson_2f; - case elfcpp::E_MIPS_MACH_LS3A: - return mach_mips_loongson_3a; + case elfcpp::E_MIPS_MACH_GS464: + return mach_mips_gs464; + + case elfcpp::E_MIPS_MACH_GS464E: + return mach_mips_gs464e; + + case elfcpp::E_MIPS_MACH_GS264E: + return mach_mips_gs264e; case elfcpp::E_MIPS_MACH_OCTEON3: return mach_mips_octeon3; @@ -8531,8 +8911,14 @@ Target_mips::elf_mips_mach(elfcpp::Elf_Word flags) case elfcpp::E_MIPS_ARCH_32R2: return mach_mipsisa32r2; + case elfcpp::E_MIPS_ARCH_32R6: + return mach_mipsisa32r6; + case elfcpp::E_MIPS_ARCH_64R2: return mach_mipsisa64r2; + + case elfcpp::E_MIPS_ARCH_64R6: + return mach_mipsisa64r6; } } @@ -8583,9 +8969,6 @@ Target_mips::mips_isa_ext_mach(unsigned int isa_ext) case elfcpp::AFL_EXT_LOONGSON_2F: return mach_mips_loongson_2f; - case elfcpp::AFL_EXT_LOONGSON_3A: - return mach_mips_loongson_3a; - case elfcpp::AFL_EXT_SB1: return mach_mips_sb1; @@ -8650,9 +9033,6 @@ Target_mips::mips_isa_ext(unsigned int mips_mach) case mach_mips_loongson_2f: return elfcpp::AFL_EXT_LOONGSON_2F; - case mach_mips_loongson_3a: - return elfcpp::AFL_EXT_LOONGSON_3A; - case mach_mips_sb1: return elfcpp::AFL_EXT_SB1; @@ -8707,12 +9087,18 @@ Target_mips::update_abiflags_isa(const std::string& name, case elfcpp::E_MIPS_ARCH_32R2: new_isa = this->level_rev(32, 2); break; + case elfcpp::E_MIPS_ARCH_32R6: + new_isa = this->level_rev(32, 6); + break; case elfcpp::E_MIPS_ARCH_64: new_isa = this->level_rev(64, 1); break; case elfcpp::E_MIPS_ARCH_64R2: new_isa = this->level_rev(64, 2); break; + case elfcpp::E_MIPS_ARCH_64R6: + new_isa = this->level_rev(64, 6); + break; default: gold_error(_("%s: Unknown architecture %s"), name.c_str(), this->elf_mips_mach_name(e_flags)); @@ -8778,7 +9164,7 @@ Target_mips::infer_abiflags( && abiflags->fp_abi != elfcpp::Val_GNU_MIPS_ABI_FP_SOFT && abiflags->fp_abi != elfcpp::Val_GNU_MIPS_ABI_FP_64A && abiflags->isa_level >= 32 - && abiflags->isa_ext != elfcpp::AFL_EXT_LOONGSON_3A) + && abiflags->ases != elfcpp::AFL_ASE_LOONGSON_EXT) abiflags->flags1 |= elfcpp::AFL_FLAGS1_ODDSPREG; } @@ -9233,6 +9619,8 @@ Target_mips::do_finalize_sections(Layout* layout, const Input_objects* input_objects, Symbol_table* symtab) { + const bool relocatable = parameters->options().relocatable(); + // Add +1 to MIPS16 and microMIPS init_ and _fini symbols so that DT_INIT and // DT_FINI have correct values. Mips_symbol* init = static_cast*>( @@ -9266,22 +9654,6 @@ Target_mips::do_finalize_sections(Layout* layout, if (this->got16_addends_.size() > 0) gold_error("Can't find matching LO16 reloc"); - // Set _gp value. - this->set_gp(layout, symtab); - - // Check for any mips16 stub sections that we can discard. - if (!parameters->options().relocatable()) - { - for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); - p != input_objects->relobj_end(); - ++p) - { - Mips_relobj* object = - Mips_relobj::as_mips_relobj(*p); - object->discard_mips16_stub_sections(symtab); - } - } - Valtype gprmask = 0; Valtype cprmask1 = 0; Valtype cprmask2 = 0; @@ -9296,6 +9668,13 @@ Target_mips::do_finalize_sections(Layout* layout, Mips_relobj* relobj = Mips_relobj::as_mips_relobj(*p); + // Check for any mips16 stub sections that we can discard. + if (!relocatable) + relobj->discard_mips16_stub_sections(symtab); + + if (!relobj->merge_processor_specific_data()) + continue; + // Merge .reginfo contents of input objects. if (relobj->has_reginfo_section()) { @@ -9307,24 +9686,6 @@ Target_mips::do_finalize_sections(Layout* layout, cprmask4 |= relobj->cprmask4(); } - Input_file::Format format = relobj->input_file()->format(); - if (format != Input_file::FORMAT_ELF) - continue; - - // If all input sections will be discarded, don't use this object - // file for merging processor specific flags. - bool should_merge_processor_specific_flags = false; - - for (unsigned int i = 1; i < relobj->shnum(); ++i) - if (relobj->output_section(i) != NULL) - { - should_merge_processor_specific_flags = true; - break; - } - - if (!should_merge_processor_specific_flags) - continue; - // Merge processor specific flags. Mips_abiflags in_abiflags; @@ -9359,7 +9720,7 @@ Target_mips::do_finalize_sections(Layout* layout, elfcpp::SHF_ALLOC, abiflags_section, ORDER_INVALID, false); - if (!parameters->options().relocatable() && os != NULL) + if (!relocatable && os != NULL) { Output_segment* abiflags_segment = layout->make_output_segment(elfcpp::PT_MIPS_ABIFLAGS, elfcpp::PF_R); @@ -9380,7 +9741,7 @@ Target_mips::do_finalize_sections(Layout* layout, elfcpp::SHF_ALLOC, reginfo_section, ORDER_INVALID, false); - if (!parameters->options().relocatable() && os != NULL) + if (!relocatable && os != NULL) { Output_segment* reginfo_segment = layout->make_output_segment(elfcpp::PT_MIPS_REGINFO, @@ -9425,7 +9786,7 @@ Target_mips::do_finalize_sections(Layout* layout, false, false); } - if (!parameters->options().relocatable() && !parameters->doing_static_link()) + if (!relocatable && !parameters->doing_static_link()) // In case there is no .got section, create one. this->got_section(symtab, layout); @@ -9435,6 +9796,9 @@ Target_mips::do_finalize_sections(Layout* layout, this->copy_relocs_.emit_mips(this->rel_dyn_section(layout), symtab, layout, this); + // Set _gp value. + this->set_gp(layout, symtab); + // Emit dynamic relocs. for (typename std::vector::iterator p = this->dyn_relocs_.begin(); p != this->dyn_relocs_.end(); @@ -9454,7 +9818,7 @@ Target_mips::do_finalize_sections(Layout* layout, symtab)); // Add NULL segment. - if (!parameters->options().relocatable()) + if (!relocatable) layout->make_output_segment(elfcpp::PT_NULL, 0); // Fill in some more dynamic tags. @@ -9466,7 +9830,7 @@ Target_mips::do_finalize_sections(Layout* layout, Output_data_dynamic* const odyn = layout->dynamic_data(); if (odyn != NULL - && !parameters->options().relocatable() + && !relocatable && !parameters->doing_static_link()) { unsigned int d_val; @@ -9479,7 +9843,7 @@ Target_mips::do_finalize_sections(Layout* layout, d_val = elfcpp::RHF_NOTPOT; odyn->add_constant(elfcpp::DT_MIPS_FLAGS, d_val); - // Save layout for using when emiting custom dynamic tags. + // Save layout for using when emitting custom dynamic tags. this->layout_ = layout; // This member holds the base address of the segment. @@ -9499,8 +9863,38 @@ Target_mips::do_finalize_sections(Layout* layout, if (this->plt_ != NULL) // DT_MIPS_PLTGOT dynamic tag odyn->add_section_address(elfcpp::DT_MIPS_PLTGOT, this->got_plt_); + + if (!parameters->options().shared()) + { + this->rld_map_ = new Output_data_zero_fill(size / 8, size / 8); + + layout->add_output_section_data(".rld_map", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), + this->rld_map_, ORDER_INVALID, false); + + // __RLD_MAP will be filled in by the runtime loader to contain + // a pointer to the _r_debug structure. + Symbol* rld_map = symtab->define_in_output_data("__RLD_MAP", NULL, + Symbol_table::PREDEFINED, + this->rld_map_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_GLOBAL, + elfcpp::STV_DEFAULT, 0, + false, false); + + if (!rld_map->is_forced_local()) + rld_map->set_needs_dynsym_entry(); + + if (!parameters->options().pie()) + // This member holds the absolute address of the debug pointer. + odyn->add_section_address(elfcpp::DT_MIPS_RLD_MAP, this->rld_map_); + else + // This member holds the offset to the debug pointer, + // relative to the address of the tag. + odyn->add_custom(elfcpp::DT_MIPS_RLD_MAP_REL); + } } - } +} // Get the custom dynamic tag value. template @@ -9536,6 +9930,16 @@ Target_mips::do_dynamic_tag_custom_value(elfcpp::DT tag) const return this->get_dt_mips_symtabno(); } + case elfcpp::DT_MIPS_RLD_MAP_REL: + { + // The MIPS_RLD_MAP_REL tag stores the offset to the debug pointer, + // relative to the address of the tag. + Output_data_dynamic* const odyn = this->layout_->dynamic_data(); + unsigned int entry_offset = + odyn->get_entry_offset(elfcpp::DT_MIPS_RLD_MAP_REL); + gold_assert(entry_offset != -1U); + return this->rld_map_->address() - (odyn->address() + entry_offset); + } default: gold_error(_("Unknown dynamic tag 0x%x"), (unsigned int)tag); } @@ -9628,10 +10032,14 @@ mips_get_size_for_reloc(unsigned int r_type, Relobj* object) case elfcpp::R_MIPS_16: case elfcpp::R_MIPS_HI16: case elfcpp::R_MIPS_LO16: + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MIPS_HIGHEST: case elfcpp::R_MIPS_GPREL16: case elfcpp::R_MIPS16_HI16: case elfcpp::R_MIPS16_LO16: case elfcpp::R_MIPS_PC16: + case elfcpp::R_MIPS_PCHI16: + case elfcpp::R_MIPS_PCLO16: case elfcpp::R_MIPS_GOT16: case elfcpp::R_MIPS16_GOT16: case elfcpp::R_MIPS_CALL16: @@ -9657,6 +10065,10 @@ mips_get_size_for_reloc(unsigned int r_type, Relobj* object) // These relocations are not byte sized case elfcpp::R_MIPS_26: case elfcpp::R_MIPS16_26: + case elfcpp::R_MIPS_PC21_S2: + case elfcpp::R_MIPS_PC26_S2: + case elfcpp::R_MIPS_PC18_S3: + case elfcpp::R_MIPS_PC19_S2: return 4; case elfcpp::R_MIPS_COPY: @@ -9970,7 +10382,9 @@ Target_mips::relocate_special_relocatable( break; case Reloc_funcs::STATUS_OVERFLOW: gold_error_at_location(relinfo, relnum, reloc.get_r_offset(), - _("relocation overflow")); + _("relocation overflow: " + "%u against local symbol %u in %s"), + r_type, r_sym, object->name().c_str()); break; case Reloc_funcs::STATUS_BAD_RELOC: gold_error_at_location(relinfo, relnum, reloc.get_r_offset(), @@ -10156,6 +10570,7 @@ Target_mips::Scan::local( } case elfcpp::R_MIPS_HI16: + case elfcpp::R_MIPS_PCHI16: case elfcpp::R_MIPS16_HI16: case elfcpp::R_MICROMIPS_HI16: // Record the reloc so that we can check whether the corresponding LO16 @@ -10166,6 +10581,7 @@ Target_mips::Scan::local( break; case elfcpp::R_MIPS_LO16: + case elfcpp::R_MIPS_PCLO16: case elfcpp::R_MIPS16_LO16: case elfcpp::R_MICROMIPS_LO16: { @@ -10358,13 +10774,16 @@ Target_mips::Scan::local( { case elfcpp::R_MIPS16_HI16: case elfcpp::R_MIPS_HI16: + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MIPS_HIGHEST: case elfcpp::R_MICROMIPS_HI16: + case elfcpp::R_MICROMIPS_HIGHER: + case elfcpp::R_MICROMIPS_HIGHEST: // Don't refuse a high part relocation if it's against // no symbol (e.g. part of a compound relocation). if (r_sym == 0) break; - - // FALLTHROUGH + // Fall through. case elfcpp::R_MIPS16_26: case elfcpp::R_MIPS_26: @@ -10499,13 +10918,6 @@ Target_mips::Scan::global( // looking for relocs that would need to refer to MIPS16 stubs. mips_sym->set_need_fn_stub(); - // A reference to _GLOBAL_OFFSET_TABLE_ implies that we need a got - // section. We check here to avoid creating a dynamic reloc against - // _GLOBAL_OFFSET_TABLE_. - if (!target->has_got_section() - && strcmp(gsym->name(), "_GLOBAL_OFFSET_TABLE_") == 0) - target->got_section(symtab, layout); - // We need PLT entries if there are static-only relocations against // an externally-defined function. This can technically occur for // shared libraries if there are branches to the symbol, although it @@ -10593,11 +11005,12 @@ Target_mips::Scan::global( // Most static relocations require pointer equality, except // for branches. mips_sym->set_pointer_equality_needed(); - // Fall through. case elfcpp::R_MIPS_26: case elfcpp::R_MIPS_PC16: + case elfcpp::R_MIPS_PC21_S2: + case elfcpp::R_MIPS_PC26_S2: case elfcpp::R_MIPS16_26: case elfcpp::R_MICROMIPS_26_S1: case elfcpp::R_MICROMIPS_PC7_S1: @@ -10861,7 +11274,11 @@ Target_mips::Scan::global( { case elfcpp::R_MIPS16_HI16: case elfcpp::R_MIPS_HI16: + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MIPS_HIGHEST: case elfcpp::R_MICROMIPS_HI16: + case elfcpp::R_MICROMIPS_HIGHER: + case elfcpp::R_MICROMIPS_HIGHEST: // Don't refuse a high part relocation if it's against // no symbol (e.g. part of a compound relocation). if (r_sym == 0) @@ -10871,8 +11288,7 @@ Target_mips::Scan::global( // and has a special meaning. if (!mips_obj->is_newabi() && strcmp(gsym->name(), "_gp_disp") == 0) break; - - // FALLTHROUGH + // Fall through. case elfcpp::R_MIPS16_26: case elfcpp::R_MIPS_26: @@ -11016,6 +11432,13 @@ Target_mips::Relocate::relocate( unsigned int r_type3; unsigned char r_ssym; typename elfcpp::Elf_types::Elf_Swxword r_addend; + // r_offset and r_type of the next relocation is needed for resolving multiple + // consecutive relocations with the same offset. + Mips_address next_r_offset = static_cast(0) - 1; + unsigned int next_r_type = elfcpp::R_MIPS_NONE; + + elfcpp::Shdr shdr(relinfo->reloc_shdr); + size_t reloc_count = shdr.get_sh_size() / shdr.get_sh_entsize(); if (rel_type == elfcpp::SHT_RELA) { @@ -11032,6 +11455,17 @@ Target_mips::Relocate::relocate( r_ssym = Mips_classify_reloc:: get_r_ssym(&rela); r_addend = rela.get_r_addend(); + // If this is not last relocation, get r_offset and r_type of the next + // relocation. + if (relnum + 1 < reloc_count) + { + const int reloc_size = elfcpp::Elf_sizes::rela_size; + const Relatype next_rela(preloc + reloc_size); + next_r_offset = next_rela.get_r_offset(); + next_r_type = + Mips_classify_reloc:: + get_r_type(&next_rela); + } } else { @@ -11042,9 +11476,19 @@ Target_mips::Relocate::relocate( r_type = Mips_classify_reloc:: get_r_type(&rel); r_ssym = 0; - r_type2 = 0; - r_type3 = 0; + r_type2 = elfcpp::R_MIPS_NONE; + r_type3 = elfcpp::R_MIPS_NONE; r_addend = 0; + // If this is not last relocation, get r_offset and r_type of the next + // relocation. + if (relnum + 1 < reloc_count) + { + const int reloc_size = elfcpp::Elf_sizes::rel_size; + const Reltype next_rel(preloc + reloc_size); + next_r_offset = next_rel.get_r_offset(); + next_r_type = Mips_classify_reloc:: + get_r_type(&next_rel); + } } typedef Mips_relocate_functions Reloc_funcs; @@ -11157,7 +11601,6 @@ Target_mips::Relocate::relocate( // // (c) the section allows direct references to MIPS16 functions. if (r_type != elfcpp::R_MIPS16_26 - && !parameters->options().relocatable() && ((mips_sym != NULL && mips_sym->has_mips16_fn_stub() && (r_type != elfcpp::R_MIPS16_CALL16 || mips_sym->need_fn_stub())) @@ -11193,7 +11636,7 @@ Target_mips::Relocate::relocate( // to a standard MIPS function, we need to redirect the call to the stub. // Note that we specifically exclude R_MIPS16_CALL16 from this behavior; // indirect calls should use an indirect stub instead. - else if (r_type == elfcpp::R_MIPS16_26 && !parameters->options().relocatable() + else if (r_type == elfcpp::R_MIPS16_26 && ((mips_sym != NULL && (mips_sym->has_mips16_call_stub() || mips_sym->has_mips16_call_fp_stub())) @@ -11255,7 +11698,6 @@ Target_mips::Relocate::relocate( // entry is used if a standard PLT entry has also been made. else if ((r_type == elfcpp::R_MIPS16_26 || r_type == elfcpp::R_MICROMIPS_26_S1) - && !parameters->options().relocatable() && mips_sym != NULL && mips_sym->has_plt_offset() && mips_sym->has_comp_plt_offset() @@ -11284,8 +11726,7 @@ Target_mips::Relocate::relocate( // symbol would be 16-bit code, and that direct jumps were therefore // acceptable. cross_mode_jump = - (!parameters->options().relocatable() - && !(gsym != NULL && gsym->is_weak_undefined()) + (!(gsym != NULL && gsym->is_weak_undefined()) && ((r_type == elfcpp::R_MIPS16_26 && !target_is_16_bit_code) || (r_type == elfcpp::R_MICROMIPS_26_S1 && !target_is_micromips_code) || ((r_type == elfcpp::R_MIPS_26 || r_type == elfcpp::R_MIPS_JALR) @@ -11307,8 +11748,7 @@ Target_mips::Relocate::relocate( unsigned int got_offset = 0; int gp_offset = 0; - bool calculate_only = false; - Valtype calculated_value = 0; + // Whether we have to extract addend from instruction. bool extract_addend = rel_type == elfcpp::SHT_REL; unsigned int r_types[3] = { r_type, r_type2, r_type3 }; @@ -11331,10 +11771,23 @@ Target_mips::Relocate::relocate( if (r_types[i] == elfcpp::R_MIPS_NONE) break; - // TODO(Vladimir) - // Check if the next relocation is for the same instruction. - calculate_only = i == 2 ? false - : r_types[i+1] != elfcpp::R_MIPS_NONE; + // If we didn't apply previous relocation, use its result as addend + // for current. + if (this->calculate_only_) + { + r_addend = this->calculated_value_; + extract_addend = false; + } + + // In the N32 and 64-bit ABIs there may be multiple consecutive + // relocations for the same offset. In that case we are + // supposed to treat the output of each relocation as the addend + // for the next. For N64 ABI, we are checking offsets only in a + // third operation in a record (r_type3). + this->calculate_only_ = + (object->is_n64() && i < 2 + ? r_types[i+1] != elfcpp::R_MIPS_NONE + : (r_offset == next_r_offset) && (next_r_type != elfcpp::R_MIPS_NONE)); if (object->is_n64()) { @@ -11374,16 +11827,18 @@ Target_mips::Relocate::relocate( break; case elfcpp::R_MIPS_16: reloc_status = Reloc_funcs::rel16(view, object, psymval, r_addend, - extract_addend, calculate_only, - &calculated_value); + extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_32: if (should_apply_static_reloc(mips_sym, r_types[i], output_section, target)) reloc_status = Reloc_funcs::rel32(view, object, psymval, r_addend, - extract_addend, calculate_only, - &calculated_value); + extract_addend, + this->calculate_only_, + &this->calculated_value_); if (mips_sym != NULL && (mips_sym->is_mips16() || mips_sym->is_micromips()) && mips_sym->global_got_area() == GGA_RELOC_ONLY) @@ -11408,14 +11863,16 @@ Target_mips::Relocate::relocate( if (should_apply_static_reloc(mips_sym, r_types[i], output_section, target)) reloc_status = Reloc_funcs::rel64(view, object, psymval, r_addend, - extract_addend, calculate_only, - &calculated_value, false); + extract_addend, + this->calculate_only_, + &this->calculated_value_, false); else if (target->is_output_n64() && r_addend != 0) // Only apply the addend. The static relocation was RELA, but the // dynamic relocation is REL, so we need to apply the addend. reloc_status = Reloc_funcs::rel64(view, object, psymval, r_addend, - extract_addend, calculate_only, - &calculated_value, true); + extract_addend, + this->calculate_only_, + &this->calculated_value_, true); break; case elfcpp::R_MIPS_REL32: gold_unreachable(); @@ -11423,8 +11880,8 @@ Target_mips::Relocate::relocate( case elfcpp::R_MIPS_PC32: reloc_status = Reloc_funcs::relpc32(view, object, psymval, address, r_addend, extract_addend, - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS16_26: @@ -11436,8 +11893,8 @@ Target_mips::Relocate::relocate( case elfcpp::R_MICROMIPS_26_S1: reloc_status = Reloc_funcs::rel26(view, object, psymval, address, gsym == NULL, r_addend, extract_addend, gsym, cross_mode_jump, - r_types[i], target->jal_to_bal(), calculate_only, - &calculated_value); + r_types[i], target->jal_to_bal(), this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_HI16: @@ -11448,8 +11905,9 @@ Target_mips::Relocate::relocate( r_addend, address, gp_disp, r_types[i], extract_addend, 0, - target, calculate_only, - &calculated_value); + target, + this->calculate_only_, + &this->calculated_value_); else if (rel_type == elfcpp::SHT_REL) reloc_status = Reloc_funcs::relhi16(view, object, psymval, r_addend, address, gp_disp, r_types[i], @@ -11465,8 +11923,8 @@ Target_mips::Relocate::relocate( reloc_status = Reloc_funcs::rello16(target, view, object, psymval, r_addend, extract_addend, address, gp_disp, r_types[i], r_sym, - rel_type, calculate_only, - &calculated_value); + rel_type, this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_LITERAL: @@ -11486,42 +11944,93 @@ Target_mips::Relocate::relocate( target->adjusted_gp_value(object), r_addend, extract_addend, gsym == NULL, r_types[i], - calculate_only, &calculated_value); + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_PC16: reloc_status = Reloc_funcs::relpc16(view, object, psymval, address, r_addend, extract_addend, - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); + break; + + case elfcpp::R_MIPS_PC21_S2: + reloc_status = Reloc_funcs::relpc21(view, object, psymval, address, + r_addend, extract_addend, + this->calculate_only_, + &this->calculated_value_); + break; + + case elfcpp::R_MIPS_PC26_S2: + reloc_status = Reloc_funcs::relpc26(view, object, psymval, address, + r_addend, extract_addend, + this->calculate_only_, + &this->calculated_value_); + break; + + case elfcpp::R_MIPS_PC18_S3: + reloc_status = Reloc_funcs::relpc18(view, object, psymval, address, + r_addend, extract_addend, + this->calculate_only_, + &this->calculated_value_); + break; + + case elfcpp::R_MIPS_PC19_S2: + reloc_status = Reloc_funcs::relpc19(view, object, psymval, address, + r_addend, extract_addend, + this->calculate_only_, + &this->calculated_value_); + break; + + case elfcpp::R_MIPS_PCHI16: + if (rel_type == elfcpp::SHT_RELA) + reloc_status = Reloc_funcs::do_relpchi16(view, object, psymval, + r_addend, address, + extract_addend, 0, + this->calculate_only_, + &this->calculated_value_); + else if (rel_type == elfcpp::SHT_REL) + reloc_status = Reloc_funcs::relpchi16(view, object, psymval, + r_addend, address, r_sym, + extract_addend); + else + gold_unreachable(); + break; + + case elfcpp::R_MIPS_PCLO16: + reloc_status = Reloc_funcs::relpclo16(view, object, psymval, r_addend, + extract_addend, address, r_sym, + rel_type, this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MICROMIPS_PC7_S1: reloc_status = Reloc_funcs::relmicromips_pc7_s1(view, object, psymval, - address, r_addend, - extract_addend, - calculate_only, - &calculated_value); + address, r_addend, + extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MICROMIPS_PC10_S1: reloc_status = Reloc_funcs::relmicromips_pc10_s1(view, object, - psymval, address, - r_addend, extract_addend, - calculate_only, - &calculated_value); + psymval, address, + r_addend, extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MICROMIPS_PC16_S1: reloc_status = Reloc_funcs::relmicromips_pc16_s1(view, object, - psymval, address, - r_addend, extract_addend, - calculate_only, - &calculated_value); + psymval, address, + r_addend, extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_GPREL32: reloc_status = Reloc_funcs::relgprel32(view, object, psymval, target->adjusted_gp_value(object), r_addend, extract_addend, - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_GOT_HI16: case elfcpp::R_MIPS_CALL_HI16: @@ -11537,8 +12046,8 @@ Target_mips::Relocate::relocate( object, r_addend); gp_offset = target->got_section()->gp_offset(got_offset, object); reloc_status = Reloc_funcs::relgot_hi16(view, gp_offset, - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); update_got_entry = changed_symbol_value; break; @@ -11556,8 +12065,8 @@ Target_mips::Relocate::relocate( object, r_addend); gp_offset = target->got_section()->gp_offset(got_offset, object); reloc_status = Reloc_funcs::relgot_lo16(view, gp_offset, - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); update_got_entry = changed_symbol_value; break; @@ -11575,12 +12084,12 @@ Target_mips::Relocate::relocate( gp_offset = target->got_section()->gp_offset(got_offset, object); if (eh_reloc(r_types[i])) reloc_status = Reloc_funcs::releh(view, gp_offset, - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); else reloc_status = Reloc_funcs::relgot(view, gp_offset, - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_CALL16: case elfcpp::R_MIPS16_CALL16: @@ -11591,7 +12100,8 @@ Target_mips::Relocate::relocate( object); gp_offset = target->got_section()->gp_offset(got_offset, object); reloc_status = Reloc_funcs::relgot(view, gp_offset, - calculate_only, &calculated_value); + this->calculate_only_, + &this->calculated_value_); // TODO(sasa): We should also initialize update_got_entry // in other place swhere relgot is called. update_got_entry = changed_symbol_value; @@ -11607,18 +12117,18 @@ Target_mips::Relocate::relocate( object); gp_offset = target->got_section()->gp_offset(got_offset, object); reloc_status = Reloc_funcs::relgot(view, gp_offset, - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); } else { if (rel_type == elfcpp::SHT_RELA) reloc_status = Reloc_funcs::do_relgot16_local(view, object, - psymval, r_addend, - extract_addend, 0, - target, - calculate_only, - &calculated_value); + psymval, r_addend, + extract_addend, 0, + target, + this->calculate_only_, + &this->calculated_value_); else if (rel_type == elfcpp::SHT_REL) reloc_status = Reloc_funcs::relgot16_local(view, object, psymval, r_addend, @@ -11642,8 +12152,9 @@ Target_mips::Relocate::relocate( GOT_TYPE_TLS_PAIR, object, r_addend); gp_offset = target->got_section()->gp_offset(got_offset, object); - reloc_status = Reloc_funcs::relgot(view, gp_offset, calculate_only, - &calculated_value); + reloc_status = Reloc_funcs::relgot(view, gp_offset, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_TLS_GOTTPREL: @@ -11658,8 +12169,9 @@ Target_mips::Relocate::relocate( GOT_TYPE_TLS_OFFSET, object, r_addend); gp_offset = target->got_section()->gp_offset(got_offset, object); - reloc_status = Reloc_funcs::relgot(view, gp_offset, calculate_only, - &calculated_value); + reloc_status = Reloc_funcs::relgot(view, gp_offset, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_TLS_LDM: @@ -11669,24 +12181,25 @@ Target_mips::Relocate::relocate( // the module index. got_offset = target->got_section()->tls_ldm_offset(object); gp_offset = target->got_section()->gp_offset(got_offset, object); - reloc_status = Reloc_funcs::relgot(view, gp_offset, calculate_only, - &calculated_value); + reloc_status = Reloc_funcs::relgot(view, gp_offset, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_GOT_PAGE: case elfcpp::R_MICROMIPS_GOT_PAGE: reloc_status = Reloc_funcs::relgotpage(target, view, object, psymval, r_addend, extract_addend, - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_GOT_OFST: case elfcpp::R_MICROMIPS_GOT_OFST: reloc_status = Reloc_funcs::relgotofst(target, view, object, psymval, r_addend, extract_addend, - local, calculate_only, - &calculated_value); + local, this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_JALR: @@ -11701,8 +12214,8 @@ Target_mips::Relocate::relocate( cross_mode_jump, r_types[i], target->jalr_to_bal(), target->jr_to_b(), - calculate_only, - &calculated_value); + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_TLS_DTPREL_HI16: @@ -11710,52 +12223,73 @@ Target_mips::Relocate::relocate( case elfcpp::R_MICROMIPS_TLS_DTPREL_HI16: reloc_status = Reloc_funcs::tlsrelhi16(view, object, psymval, elfcpp::DTP_OFFSET, r_addend, - extract_addend, calculate_only, - &calculated_value); + extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_TLS_DTPREL_LO16: case elfcpp::R_MIPS16_TLS_DTPREL_LO16: case elfcpp::R_MICROMIPS_TLS_DTPREL_LO16: reloc_status = Reloc_funcs::tlsrello16(view, object, psymval, elfcpp::DTP_OFFSET, r_addend, - extract_addend, calculate_only, - &calculated_value); + extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_TLS_DTPREL32: case elfcpp::R_MIPS_TLS_DTPREL64: reloc_status = Reloc_funcs::tlsrel32(view, object, psymval, elfcpp::DTP_OFFSET, r_addend, - extract_addend, calculate_only, - &calculated_value); + extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_TLS_TPREL_HI16: case elfcpp::R_MIPS16_TLS_TPREL_HI16: case elfcpp::R_MICROMIPS_TLS_TPREL_HI16: reloc_status = Reloc_funcs::tlsrelhi16(view, object, psymval, elfcpp::TP_OFFSET, r_addend, - extract_addend, calculate_only, - &calculated_value); + extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_TLS_TPREL_LO16: case elfcpp::R_MIPS16_TLS_TPREL_LO16: case elfcpp::R_MICROMIPS_TLS_TPREL_LO16: reloc_status = Reloc_funcs::tlsrello16(view, object, psymval, elfcpp::TP_OFFSET, r_addend, - extract_addend, calculate_only, - &calculated_value); + extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_TLS_TPREL32: case elfcpp::R_MIPS_TLS_TPREL64: reloc_status = Reloc_funcs::tlsrel32(view, object, psymval, elfcpp::TP_OFFSET, r_addend, - extract_addend, calculate_only, - &calculated_value); + extract_addend, + this->calculate_only_, + &this->calculated_value_); break; case elfcpp::R_MIPS_SUB: case elfcpp::R_MICROMIPS_SUB: reloc_status = Reloc_funcs::relsub(view, object, psymval, r_addend, extract_addend, - calculate_only, &calculated_value); + this->calculate_only_, + &this->calculated_value_); + break; + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MICROMIPS_HIGHER: + reloc_status = Reloc_funcs::relhigher(view, object, psymval, r_addend, + extract_addend, + this->calculate_only_, + &this->calculated_value_); + break; + case elfcpp::R_MIPS_HIGHEST: + case elfcpp::R_MICROMIPS_HIGHEST: + reloc_status = Reloc_funcs::relhighest(view, object, psymval, + r_addend, extract_addend, + this->calculate_only_, + &this->calculated_value_); break; default: gold_error_at_location(relinfo, relnum, r_offset, @@ -11772,12 +12306,9 @@ Target_mips::Relocate::relocate( else got->update_got_entry(got_offset, psymval->value(object, 0)); } - - r_addend = calculated_value; } - bool jal_shuffle = jal_reloc(r_type) ? !parameters->options().relocatable() - : false; + bool jal_shuffle = jal_reloc(r_type); Reloc_funcs::mips_reloc_shuffle(view, r_type, jal_shuffle); // Report any errors. @@ -11786,13 +12317,30 @@ Target_mips::Relocate::relocate( case Reloc_funcs::STATUS_OKAY: break; case Reloc_funcs::STATUS_OVERFLOW: - gold_error_at_location(relinfo, relnum, r_offset, - _("relocation overflow")); + if (gsym == NULL) + gold_error_at_location(relinfo, relnum, r_offset, + _("relocation overflow: " + "%u against local symbol %u in %s"), + r_type, r_sym, object->name().c_str()); + else if (gsym->is_defined() && gsym->source() == Symbol::FROM_OBJECT) + gold_error_at_location(relinfo, relnum, r_offset, + _("relocation overflow: " + "%u against '%s' defined in %s"), + r_type, gsym->demangled_name().c_str(), + gsym->object()->name().c_str()); + else + gold_error_at_location(relinfo, relnum, r_offset, + _("relocation overflow: %u against '%s'"), + r_type, gsym->demangled_name().c_str()); break; case Reloc_funcs::STATUS_BAD_RELOC: gold_error_at_location(relinfo, relnum, r_offset, _("unexpected opcode while processing relocation")); break; + case Reloc_funcs::STATUS_PCREL_UNALIGNED: + gold_error_at_location(relinfo, relnum, r_offset, + _("unaligned PC-relative relocation")); + break; default: gold_unreachable(); } @@ -11818,10 +12366,14 @@ Target_mips::Scan::get_reference_flags( case elfcpp::R_MIPS_64: case elfcpp::R_MIPS_HI16: case elfcpp::R_MIPS_LO16: + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MIPS_HIGHEST: case elfcpp::R_MIPS16_HI16: case elfcpp::R_MIPS16_LO16: case elfcpp::R_MICROMIPS_HI16: case elfcpp::R_MICROMIPS_LO16: + case elfcpp::R_MICROMIPS_HIGHER: + case elfcpp::R_MICROMIPS_HIGHEST: return Symbol::ABSOLUTE_REF; case elfcpp::R_MIPS_26: @@ -11829,6 +12381,10 @@ Target_mips::Scan::get_reference_flags( case elfcpp::R_MICROMIPS_26_S1: return Symbol::FUNCTION_CALL | Symbol::ABSOLUTE_REF; + case elfcpp::R_MIPS_PC18_S3: + case elfcpp::R_MIPS_PC19_S2: + case elfcpp::R_MIPS_PCHI16: + case elfcpp::R_MIPS_PCLO16: case elfcpp::R_MIPS_GPREL32: case elfcpp::R_MIPS_GPREL16: case elfcpp::R_MIPS_REL32: @@ -11837,6 +12393,8 @@ Target_mips::Scan::get_reference_flags( case elfcpp::R_MIPS_PC16: case elfcpp::R_MIPS_PC32: + case elfcpp::R_MIPS_PC21_S2: + case elfcpp::R_MIPS_PC26_S2: case elfcpp::R_MIPS_JALR: case elfcpp::R_MICROMIPS_JALR: return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF; @@ -11887,7 +12445,6 @@ Target_mips::Scan::get_reference_flags( case elfcpp::R_MIPS_COPY: case elfcpp::R_MIPS_JUMP_SLOT: default: - gold_unreachable(); // Not expected. We will give an error later. return 0; } @@ -11977,8 +12534,12 @@ Target_mips::elf_mips_mach_name(elfcpp::Elf_Word e_flags) return "mips:loongson_2e"; case elfcpp::E_MIPS_MACH_LS2F: return "mips:loongson_2f"; - case elfcpp::E_MIPS_MACH_LS3A: - return "mips:loongson_3a"; + case elfcpp::E_MIPS_MACH_GS464: + return "mips:gs464"; + case elfcpp::E_MIPS_MACH_GS464E: + return "mips:gs464e"; + case elfcpp::E_MIPS_MACH_GS264E: + return "mips:gs264e"; case elfcpp::E_MIPS_MACH_OCTEON: return "mips:octeon"; case elfcpp::E_MIPS_MACH_OCTEON2: @@ -12015,8 +12576,14 @@ Target_mips::elf_mips_mach_name(elfcpp::Elf_Word e_flags) case elfcpp::E_MIPS_ARCH_32R2: return "mips:isa32r2"; + case elfcpp::E_MIPS_ARCH_32R6: + return "mips:isa32r6"; + case elfcpp::E_MIPS_ARCH_64R2: return "mips:isa64r2"; + + case elfcpp::E_MIPS_ARCH_64R6: + return "mips:isa64r6"; } } return "unknown CPU"; @@ -12048,6 +12615,7 @@ const Target::Target_info Target_mips::mips_info = NULL, // attributes_vendor "__start", // entry_symbol_name 32, // hash_entry_size + elfcpp::SHT_PROGBITS, // unwind_section_type }; template @@ -12088,6 +12656,7 @@ const Target::Target_info Target_mips_nacl::mips_nacl_info = NULL, // attributes_vendor "_start", // entry_symbol_name 32, // hash_entry_size + elfcpp::SHT_PROGBITS, // unwind_section_type }; // Target selector for Mips. Note this is never instantiated directly.