X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gold%2Fpowerpc.cc;h=d8e8b8251e1e255d6927adc01b691d4e9044742e;hb=3c892704a98fe65a84c0a11ee4fb84988a7336b4;hp=36b5790d3035a447a9c58c46eedc437a849bb509;hpb=f59f41f3e62c417ef569b65a01cc2e657ec9a94f;p=external%2Fbinutils.git diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 36b5790..d8e8b82 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -1,6 +1,6 @@ // powerpc.cc -- powerpc target support for gold. -// Copyright 2008, 2009 Free Software Foundation, Inc. +// Copyright 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. // Written by David S. Miller // and David Edelsohn @@ -62,26 +62,26 @@ class Target_powerpc : public Sized_target { } - // Process the relocations to determine unreferenced sections for + // Process the relocations to determine unreferenced sections for // garbage collection. void gc_process_relocs(Symbol_table* symtab, - Layout* layout, - Sized_relobj* object, - unsigned int data_shndx, - unsigned int sh_type, - const unsigned char* prelocs, - size_t reloc_count, - Output_section* output_section, - bool needs_special_offset_handling, - size_t local_symbol_count, - const unsigned char* plocal_symbols); + Layout* layout, + Sized_relobj_file* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); // Scan the relocations to look for symbol adjustments. void scan_relocs(Symbol_table* symtab, Layout* layout, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int data_shndx, unsigned int sh_type, const unsigned char* prelocs, @@ -116,7 +116,7 @@ class Target_powerpc : public Sized_target void scan_relocatable_relocs(Symbol_table* symtab, Layout* layout, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int data_shndx, unsigned int sh_type, const unsigned char* prelocs, @@ -151,12 +151,33 @@ class Target_powerpc : public Sized_target // Return the size of the GOT section. section_size_type - got_size() + got_size() const { gold_assert(this->got_ != NULL); return this->got_->data_size(); } + // Return the number of entries in the GOT. + unsigned int + got_entry_count() const + { + if (this->got_ == NULL) + return 0; + return this->got_size() / (size / 8); + } + + // Return the number of entries in the PLT. + unsigned int + plt_entry_count() const; + + // Return the offset of the first non-reserved PLT entry. + unsigned int + first_plt_entry_offset() const; + + // Return the size of each PLT entry. + unsigned int + plt_entry_size() const; + private: // The class which scans relocations. @@ -167,9 +188,12 @@ class Target_powerpc : public Sized_target : issued_non_pic_error_(false) { } + static inline int + get_reference_flags(unsigned int r_type); + inline void local(Symbol_table* symtab, Layout* layout, Target_powerpc* target, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, const elfcpp::Rela& reloc, unsigned int r_type, @@ -177,19 +201,41 @@ class Target_powerpc : public Sized_target inline void global(Symbol_table* symtab, Layout* layout, Target_powerpc* target, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, const elfcpp::Rela& reloc, unsigned int r_type, Symbol* gsym); + inline bool + local_reloc_may_be_function_pointer(Symbol_table* , Layout* , + Target_powerpc* , + Sized_relobj_file* , + unsigned int , + Output_section* , + const elfcpp::Rela& , + unsigned int , + const elfcpp::Sym&) + { return false; } + + inline bool + global_reloc_may_be_function_pointer(Symbol_table* , Layout* , + Target_powerpc* , + Sized_relobj_file* , + unsigned int , + Output_section* , + const elfcpp::Rela& , + unsigned int , Symbol*) + { return false; } + private: static void - unsupported_reloc_local(Sized_relobj*, + unsupported_reloc_local(Sized_relobj_file*, unsigned int r_type); static void - unsupported_reloc_global(Sized_relobj*, + unsupported_reloc_global(Sized_relobj_file*, unsigned int r_type, Symbol*); static void @@ -224,7 +270,7 @@ class Target_powerpc : public Sized_target inline void relocate_tls(const Relocate_info*, Target_powerpc* target, - size_t relnum, const elfcpp::Rela&, + size_t relnum, const elfcpp::Rela&, unsigned int r_type, const Sized_symbol*, const Symbol_value*, unsigned char*, @@ -248,7 +294,7 @@ class Target_powerpc : public Sized_target Output_data_space* got2_section() const { - gold_assert (this->got2_ != NULL); + gold_assert(this->got2_ != NULL); return this->got2_; } @@ -256,7 +302,7 @@ class Target_powerpc : public Sized_target Output_data_space* toc_section() const { - gold_assert (this->toc_ != NULL); + gold_assert(this->toc_ != NULL); return this->toc_; } @@ -267,7 +313,7 @@ class Target_powerpc : public Sized_target // Create a GOT entry for the TLS module index. unsigned int got_mod_index_entry(Symbol_table* symtab, Layout* layout, - Sized_relobj* object); + Sized_relobj_file* object); // Get the PLT section. const Output_data_plt_powerpc* @@ -284,7 +330,7 @@ class Target_powerpc : public Sized_target // Copy a relocation against a global symbol. void copy_reloc(Symbol_table* symtab, Layout* layout, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int shndx, Output_section* output_section, Symbol* sym, const elfcpp::Rela& reloc) { @@ -299,6 +345,9 @@ class Target_powerpc : public Sized_target static Target::Target_info powerpc_info; // The types of GOT entries needed for this platform. + // These values are exposed to the ABI in an incremental link. + // Do not renumber existing values without changing the version + // number of the .gnu_incremental_inputs section. enum Got_type { GOT_TYPE_STANDARD = 0, // GOT entry for a regular symbol @@ -334,15 +383,20 @@ Target::Target_info Target_powerpc<32, true>::powerpc_info = false, // has_resolve false, // has_code_fill true, // is_default_stack_executable + false, // can_icf_inline_merge_sections '\0', // wrap_char "/usr/lib/ld.so.1", // dynamic_linker 0x10000000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) 4 * 1024, // common_pagesize (overridable by -z common-page-size) + false, // isolate_execinstr + 0, // rosegment_gap elfcpp::SHN_UNDEF, // small_common_shndx elfcpp::SHN_UNDEF, // large_common_shndx 0, // small_common_section_flags - 0 // large_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; template<> @@ -355,15 +409,20 @@ Target::Target_info Target_powerpc<32, false>::powerpc_info = false, // has_resolve false, // has_code_fill true, // is_default_stack_executable + false, // can_icf_inline_merge_sections '\0', // wrap_char "/usr/lib/ld.so.1", // dynamic_linker 0x10000000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) 4 * 1024, // common_pagesize (overridable by -z common-page-size) + false, // isolate_execinstr + 0, // rosegment_gap elfcpp::SHN_UNDEF, // small_common_shndx elfcpp::SHN_UNDEF, // large_common_shndx 0, // small_common_section_flags - 0 // large_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; template<> @@ -376,15 +435,20 @@ Target::Target_info Target_powerpc<64, true>::powerpc_info = false, // has_resolve false, // has_code_fill true, // is_default_stack_executable + false, // can_icf_inline_merge_sections '\0', // wrap_char "/usr/lib/ld.so.1", // dynamic_linker 0x10000000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) 8 * 1024, // common_pagesize (overridable by -z common-page-size) + false, // isolate_execinstr + 0, // rosegment_gap elfcpp::SHN_UNDEF, // small_common_shndx elfcpp::SHN_UNDEF, // large_common_shndx 0, // small_common_section_flags - 0 // large_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; template<> @@ -397,15 +461,20 @@ Target::Target_info Target_powerpc<64, false>::powerpc_info = false, // has_resolve false, // has_code_fill true, // is_default_stack_executable + false, // can_icf_inline_merge_sections '\0', // wrap_char "/usr/lib/ld.so.1", // dynamic_linker 0x10000000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) 8 * 1024, // common_pagesize (overridable by -z common-page-size) + false, // isolate_execinstr + 0, // rosegment_gap elfcpp::SHN_UNDEF, // small_common_shndx elfcpp::SHN_UNDEF, // large_common_shndx 0, // small_common_section_flags - 0 // large_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; template @@ -439,7 +508,7 @@ private: rela(unsigned char* view, unsigned int right_shift, elfcpp::Elf_Xword dst_mask, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Swap::Valtype addend) { @@ -460,7 +529,7 @@ private: static inline void rela_ua(unsigned char* view, unsigned int right_shift, elfcpp::Elf_Xword dst_mask, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Swap::Valtype addend) { @@ -482,7 +551,7 @@ private: static inline void pcrela(unsigned char* view, unsigned int right_shift, elfcpp::Elf_Xword dst_mask, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Swap::Valtype addend, typename elfcpp::Elf_types::Elf_Addr address) @@ -502,7 +571,7 @@ private: template static inline void pcrela_unaligned(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Swap::Valtype addend, typename elfcpp::Elf_types::Elf_Addr address) @@ -521,7 +590,7 @@ public: // R_POWERPC_REL32: (Symbol + Addend - Address) static inline void rel32(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend, typename elfcpp::Elf_types::Elf_Addr address) @@ -530,7 +599,7 @@ public: // R_POWERPC_REL24: (Symbol + Addend - Address) & 0x3fffffc static inline void rel24(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend, typename elfcpp::Elf_types::Elf_Addr address) @@ -542,7 +611,7 @@ public: // R_POWERPC_REL14: (Symbol + Addend - Address) & 0xfffc static inline void rel14(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend, typename elfcpp::Elf_types::Elf_Addr address) @@ -560,7 +629,7 @@ public: static inline void addr16(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend) { This_reloc::rela16(view, object, psymval, addend); } @@ -583,7 +652,7 @@ public: static inline void addr16_lo(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend) { This_reloc::rela16(view, object, psymval, addend); } @@ -599,7 +668,7 @@ public: static inline void addr16_hi(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend) { @@ -627,7 +696,7 @@ public: static inline void addr16_ha(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend) { @@ -645,7 +714,7 @@ public: // R_PPC_REL16: (Symbol + Addend - Address) & 0xffff static inline void rel16(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend, typename elfcpp::Elf_types::Elf_Addr address) @@ -654,7 +723,7 @@ public: // R_PPC_REL16_LO: (Symbol + Addend - Address) & 0xffff static inline void rel16_lo(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend, typename elfcpp::Elf_types::Elf_Addr address) @@ -663,7 +732,7 @@ public: // R_PPC_REL16_HI: ((Symbol + Addend - Address) >> 16) & 0xffff static inline void rel16_hi(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend, typename elfcpp::Elf_types::Elf_Addr address) @@ -677,7 +746,7 @@ public: // relocation is negative, add one. static inline void rel16_ha(unsigned char* view, - const Sized_relobj* object, + const Sized_relobj_file* object, const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr addend, typename elfcpp::Elf_types::Elf_Addr address) @@ -708,7 +777,7 @@ Target_powerpc::got_section(Symbol_table* symtab, layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->got_, false); + this->got_, ORDER_DATA, false); // Create the GOT2 or TOC in the .got section. if (size == 32) @@ -717,7 +786,7 @@ Target_powerpc::got_section(Symbol_table* symtab, layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->got2_, false); + this->got2_, ORDER_DATA, false); } else { @@ -725,11 +794,12 @@ Target_powerpc::got_section(Symbol_table* symtab, layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->toc_, false); + this->toc_, ORDER_DATA, false); } // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section. symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + Symbol_table::PREDEFINED, this->got_, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, @@ -751,7 +821,8 @@ Target_powerpc::rela_dyn_section(Layout* layout) gold_assert(layout != NULL); this->rela_dyn_ = new Reloc_section(parameters->options().combreloc()); layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rela_dyn_, true); + elfcpp::SHF_ALLOC, this->rela_dyn_, + ORDER_DYNAMIC_RELOCS, false); } return this->rela_dyn_; } @@ -776,6 +847,21 @@ class Output_data_plt_powerpc : public Output_section_data return this->rel_; } + // Return the number of PLT entries. + unsigned int + entry_count() const + { return this->count_; } + + // Return the offset of the first non-reserved PLT entry. + static unsigned int + first_plt_entry_offset() + { return 4 * base_plt_entry_size; } + + // Return the size of a PLT entry. + static unsigned int + get_plt_entry_size() + { return base_plt_entry_size; } + protected: void do_adjust_output_section(Output_section* os); @@ -811,7 +897,8 @@ Output_data_plt_powerpc::Output_data_plt_powerpc(Layout* layou { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rel_, true); + elfcpp::SHF_ALLOC, this->rel_, + ORDER_DYNAMIC_PLT_RELOCS, false); } template @@ -873,7 +960,7 @@ static const unsigned int addis_r12_r2 = 0x3d820000; /* addis %r12,%r2,xxx@h static const unsigned int std_r2_40r1 = 0xf8410028; /* std %r2,40(%r1) */ static const unsigned int ld_r11_0r12 = 0xe96c0000; /* ld %r11,xxx+0@l(%r12) */ static const unsigned int ld_r2_0r12 = 0xe84c0000; /* ld %r2,xxx+8@l(%r12) */ - /* ld %r11,xxx+16@l(%r12) */ + /* ld %r11,xxx+16@l(%r12) */ // Write out the PLT. @@ -935,15 +1022,21 @@ Target_powerpc::make_plt_entry(Symbol_table* symtab, // Create the GOT section first. this->got_section(symtab, layout); + // Ensure that .rela.dyn always appears before .rela.plt This is + // necessary due to how, on PowerPC and some other targets, .rela.dyn + // needs to include .rela.plt in it's range. + this->rela_dyn_section(layout); + this->plt_ = new Output_data_plt_powerpc(layout); layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR | elfcpp::SHF_WRITE), - this->plt_, false); + this->plt_, ORDER_PLT, false); // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section. symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL, + Symbol_table::PREDEFINED, this->plt_, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, @@ -954,13 +1047,43 @@ Target_powerpc::make_plt_entry(Symbol_table* symtab, this->plt_->add_entry(gsym); } +// Return the number of entries in the PLT. + +template +unsigned int +Target_powerpc::plt_entry_count() const +{ + if (this->plt_ == NULL) + return 0; + return this->plt_->entry_count(); +} + +// Return the offset of the first non-reserved PLT entry. + +template +unsigned int +Target_powerpc::first_plt_entry_offset() const +{ + return Output_data_plt_powerpc::first_plt_entry_offset(); +} + +// Return the size of each PLT entry. + +template +unsigned int +Target_powerpc::plt_entry_size() const +{ + return Output_data_plt_powerpc::get_plt_entry_size(); +} + // Create a GOT entry for the TLS module index. template unsigned int -Target_powerpc::got_mod_index_entry(Symbol_table* symtab, - Layout* layout, - Sized_relobj* object) +Target_powerpc::got_mod_index_entry( + Symbol_table* symtab, + Layout* layout, + Sized_relobj_file* object) { if (this->got_mod_index_offset_ == -1U) { @@ -998,12 +1121,75 @@ optimize_tls_reloc(bool /* is_final */, int r_type) } } +// Get the Reference_flags for a particular relocation. + +template +int +Target_powerpc::Scan::get_reference_flags( + unsigned int r_type) +{ + switch (r_type) + { + case elfcpp::R_POWERPC_NONE: + case elfcpp::R_POWERPC_GNU_VTINHERIT: + case elfcpp::R_POWERPC_GNU_VTENTRY: + case elfcpp::R_PPC64_TOC: + // No symbol reference. + return 0; + + case elfcpp::R_POWERPC_ADDR16: + case elfcpp::R_POWERPC_ADDR16_LO: + case elfcpp::R_POWERPC_ADDR16_HI: + case elfcpp::R_POWERPC_ADDR16_HA: + case elfcpp::R_POWERPC_ADDR32: + case elfcpp::R_PPC64_ADDR64: + return Symbol::ABSOLUTE_REF; + + case elfcpp::R_POWERPC_REL24: + case elfcpp::R_PPC_LOCAL24PC: + case elfcpp::R_PPC_REL16: + case elfcpp::R_PPC_REL16_LO: + case elfcpp::R_PPC_REL16_HI: + case elfcpp::R_PPC_REL16_HA: + return Symbol::RELATIVE_REF; + + case elfcpp::R_PPC_PLTREL24: + return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF; + + case elfcpp::R_POWERPC_GOT16: + case elfcpp::R_POWERPC_GOT16_LO: + case elfcpp::R_POWERPC_GOT16_HI: + case elfcpp::R_POWERPC_GOT16_HA: + case elfcpp::R_PPC64_TOC16: + case elfcpp::R_PPC64_TOC16_LO: + case elfcpp::R_PPC64_TOC16_HI: + case elfcpp::R_PPC64_TOC16_HA: + case elfcpp::R_PPC64_TOC16_DS: + case elfcpp::R_PPC64_TOC16_LO_DS: + // Absolute in GOT. + return Symbol::ABSOLUTE_REF; + + case elfcpp::R_POWERPC_GOT_TPREL16: + case elfcpp::R_POWERPC_TLS: + return Symbol::TLS_REF; + + case elfcpp::R_POWERPC_COPY: + case elfcpp::R_POWERPC_GLOB_DAT: + case elfcpp::R_POWERPC_JMP_SLOT: + case elfcpp::R_POWERPC_RELATIVE: + case elfcpp::R_POWERPC_DTPMOD: + default: + // Not expected. We will give an error later. + return 0; + } +} + // Report an unsupported relocation against a local symbol. template void Target_powerpc::Scan::unsupported_reloc_local( - Sized_relobj* object, + Sized_relobj_file* object, unsigned int r_type) { gold_error(_("%s: unsupported reloc %u against local symbol"), @@ -1111,7 +1297,7 @@ Target_powerpc::Scan::local( Symbol_table* symtab, Layout* layout, Target_powerpc* target, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, const elfcpp::Rela& reloc, @@ -1133,27 +1319,27 @@ Target_powerpc::Scan::local( // executable), we need to create a dynamic relocation for // this location. if (parameters->options().output_is_position_independent()) - { - Reloc_section* rela_dyn = target->rela_dyn_section(layout); + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); check_non_pic(object, r_type); - if (lsym.get_st_type() != elfcpp::STT_SECTION) - { - unsigned int r_sym = elfcpp::elf_r_sym(reloc.get_r_info()); - rela_dyn->add_local(object, r_sym, r_type, output_section, + if (lsym.get_st_type() != elfcpp::STT_SECTION) + { + unsigned int r_sym = elfcpp::elf_r_sym(reloc.get_r_info()); + rela_dyn->add_local(object, r_sym, r_type, output_section, data_shndx, reloc.get_r_offset(), reloc.get_r_addend()); - } - else - { + } + else + { unsigned int r_sym = elfcpp::elf_r_sym(reloc.get_r_info()); - gold_assert(lsym.get_st_value() == 0); - rela_dyn->add_local_relative(object, r_sym, r_type, + gold_assert(lsym.get_st_value() == 0); + rela_dyn->add_local_relative(object, r_sym, r_type, output_section, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); - } - } + reloc.get_r_addend(), false); + } + } break; case elfcpp::R_POWERPC_REL24: @@ -1174,8 +1360,8 @@ Target_powerpc::Scan::local( case elfcpp::R_PPC64_TOC16_DS: case elfcpp::R_PPC64_TOC16_LO_DS: { - // The symbol requires a GOT entry. - Output_data_got* got; + // The symbol requires a GOT entry. + Output_data_got* got; unsigned int r_sym; got = target->got_section(symtab, layout); @@ -1194,9 +1380,9 @@ Target_powerpc::Scan::local( object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off); rela_dyn->add_local_relative(object, r_sym, elfcpp::R_POWERPC_RELATIVE, - got, off, 0); + got, off, 0, false); } - } + } else got->add_local(object, r_sym, GOT_TYPE_STANDARD); } @@ -1229,7 +1415,7 @@ Target_powerpc::Scan::local( template void Target_powerpc::Scan::unsupported_reloc_global( - Sized_relobj* object, + Sized_relobj_file* object, unsigned int r_type, Symbol* gsym) { @@ -1245,7 +1431,7 @@ Target_powerpc::Scan::global( Symbol_table* symtab, Layout* layout, Target_powerpc* target, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int data_shndx, Output_section* output_section, const elfcpp::Rela& reloc, @@ -1268,8 +1454,8 @@ Target_powerpc::Scan::global( // if the symbol is defined in the output file and is protected // or hidden. if (gsym->is_defined() - && !gsym->is_from_dynobj() - && !gsym->is_preemptible()) + && !gsym->is_from_dynobj() + && !gsym->is_preemptible()) break; target->make_plt_entry(symtab, layout, gsym); break; @@ -1281,38 +1467,38 @@ Target_powerpc::Scan::global( case elfcpp::R_POWERPC_ADDR32: case elfcpp::R_PPC64_ADDR64: { - // Make a PLT entry if necessary. - if (gsym->needs_plt_entry()) - { - target->make_plt_entry(symtab, layout, gsym); - // Since this is not a PC-relative relocation, we may be - // taking the address of a function. In that case we need to - // set the entry in the dynamic symbol table to the address of - // the PLT entry. - if (gsym->is_from_dynobj() && !parameters->options().shared()) - gsym->set_needs_dynsym_value(); - } - // Make a dynamic relocation if necessary. - if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) - { - if (gsym->may_need_copy_reloc()) - { - target->copy_reloc(symtab, layout, object, - data_shndx, output_section, gsym, reloc); - } - else if ((r_type == elfcpp::R_POWERPC_ADDR32 + // Make a PLT entry if necessary. + if (gsym->needs_plt_entry()) + { + target->make_plt_entry(symtab, layout, gsym); + // Since this is not a PC-relative relocation, we may be + // taking the address of a function. In that case we need to + // set the entry in the dynamic symbol table to the address of + // the PLT entry. + if (gsym->is_from_dynobj() && !parameters->options().shared()) + gsym->set_needs_dynsym_value(); + } + // Make a dynamic relocation if necessary. + if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type))) + { + if (gsym->may_need_copy_reloc()) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, reloc); + } + else if ((r_type == elfcpp::R_POWERPC_ADDR32 || r_type == elfcpp::R_PPC64_ADDR64) - && gsym->can_use_relative_reloc(false)) - { - Reloc_section* rela_dyn = target->rela_dyn_section(layout); - rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE, + && gsym->can_use_relative_reloc(false)) + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE, output_section, object, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); - } - else - { - Reloc_section* rela_dyn = target->rela_dyn_section(layout); + reloc.get_r_addend(), false); + } + else + { + Reloc_section* rela_dyn = target->rela_dyn_section(layout); check_non_pic(object, r_type); if (gsym->is_from_dynobj() @@ -1327,9 +1513,9 @@ Target_powerpc::Scan::global( output_section, object, data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); - } - } + reloc.get_r_addend(), false); + } + } } break; @@ -1343,10 +1529,7 @@ Target_powerpc::Scan::global( if (gsym->needs_plt_entry()) target->make_plt_entry(symtab, layout, gsym); // Make a dynamic relocation if necessary. - int flags = Symbol::NON_PIC_REF; - if (gsym->type() == elfcpp::STT_FUNC) - flags |= Symbol::FUNCTION_CALL; - if (gsym->needs_dynamic_reloc(flags)) + if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type))) { if (gsym->may_need_copy_reloc()) { @@ -1377,31 +1560,31 @@ Target_powerpc::Scan::global( case elfcpp::R_PPC64_TOC16_DS: case elfcpp::R_PPC64_TOC16_LO_DS: { - // The symbol requires a GOT entry. - Output_data_got* got; + // The symbol requires a GOT entry. + Output_data_got* got; got = target->got_section(symtab, layout); - if (gsym->final_value_is_known()) - got->add_global(gsym, GOT_TYPE_STANDARD); - else - { - // If this symbol is not fully resolved, we need to add a - // dynamic relocation for it. - Reloc_section* rela_dyn = target->rela_dyn_section(layout); - if (gsym->is_from_dynobj() - || gsym->is_undefined() - || gsym->is_preemptible()) - got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn, - elfcpp::R_POWERPC_GLOB_DAT); - else if (!gsym->has_got_offset(GOT_TYPE_STANDARD)) - { + if (gsym->final_value_is_known()) + got->add_global(gsym, GOT_TYPE_STANDARD); + else + { + // If this symbol is not fully resolved, we need to add a + // dynamic relocation for it. + Reloc_section* rela_dyn = target->rela_dyn_section(layout); + if (gsym->is_from_dynobj() + || gsym->is_undefined() + || gsym->is_preemptible()) + got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn, + elfcpp::R_POWERPC_GLOB_DAT); + else if (!gsym->has_got_offset(GOT_TYPE_STANDARD)) + { unsigned int off = got->add_constant(0); gsym->set_got_offset(GOT_TYPE_STANDARD, off); rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE, - got, off, 0); + got, off, 0, false); } - } + } } break; @@ -1439,7 +1622,7 @@ void Target_powerpc::gc_process_relocs( Symbol_table* symtab, Layout* layout, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int data_shndx, unsigned int, const unsigned char* prelocs, @@ -1452,7 +1635,8 @@ Target_powerpc::gc_process_relocs( typedef Target_powerpc Powerpc; typedef typename Target_powerpc::Scan Scan; - gold::gc_process_relocs( + gold::gc_process_relocs( symtab, layout, this, @@ -1473,7 +1657,7 @@ void Target_powerpc::scan_relocs( Symbol_table* symtab, Layout* layout, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int data_shndx, unsigned int sh_type, const unsigned char* prelocs, @@ -1502,8 +1686,11 @@ Target_powerpc::scan_relocs( Output_section* os = layout->add_output_section_data(".sdata", 0, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - sdata, false); + sdata, + ORDER_SMALL_DATA, + false); symtab->define_in_output_data("_SDA_BASE_", NULL, + Symbol_table::PREDEFINED, os, 32768, 0, elfcpp::STT_OBJECT, @@ -1536,37 +1723,11 @@ Target_powerpc::do_finalize_sections( Symbol_table*) { // Fill in some more dynamic tags. - Output_data_dynamic* const odyn = layout->dynamic_data(); - if (odyn != NULL) - { - if (this->plt_ != NULL - && this->plt_->output_section() != NULL) - { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); - - odyn->add_section_address(elfcpp::DT_PLTGOT, this->plt_); - } - - if (this->rela_dyn_ != NULL - && this->rela_dyn_->output_section() != NULL) - { - const Output_data* od = this->rela_dyn_; - odyn->add_section_address(elfcpp::DT_RELA, od); - odyn->add_section_size(elfcpp::DT_RELASZ, od); - odyn->add_constant(elfcpp::DT_RELAENT, - elfcpp::Elf_sizes::rela_size); - } - - if (!parameters->options().shared()) - { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); - } - } + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(false, this->plt_, rel_plt, + this->rela_dyn_, true, size == 32); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. @@ -1597,12 +1758,7 @@ Target_powerpc::Relocate::relocate( // Pick the value to use for symbols defined in shared objects. Symbol_value symval; if (gsym != NULL - && gsym->use_plt_offset(r_type == elfcpp::R_POWERPC_REL24 - || r_type == elfcpp::R_PPC_LOCAL24PC - || r_type == elfcpp::R_PPC_REL16 - || r_type == elfcpp::R_PPC_REL16_LO - || r_type == elfcpp::R_PPC_REL16_HI - || r_type == elfcpp::R_PPC_REL16_HA)) + && gsym->use_plt_offset(Scan::get_reference_flags(r_type))) { elfcpp::Elf_Xword value; @@ -1613,13 +1769,12 @@ Target_powerpc::Relocate::relocate( psymval = &symval; } - const Sized_relobj* object = relinfo->object; + const Sized_relobj_file* object = relinfo->object; elfcpp::Elf_Xword addend = rela.get_r_addend(); // Get the GOT offset if needed. Unlike i386 and x86_64, our GOT // pointer points to the beginning, not the end, of the table. // So we just use the plain offset. - bool have_got_offset = false; unsigned int got_offset = 0; unsigned int got2_offset = 0; switch (r_type) @@ -1641,21 +1796,20 @@ Target_powerpc::Relocate::relocate( case elfcpp::R_PPC64_GOT16_DS: case elfcpp::R_PPC64_GOT16_LO_DS: if (gsym != NULL) - { - gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); - got_offset = gsym->got_offset(GOT_TYPE_STANDARD); - } + { + gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); + got_offset = gsym->got_offset(GOT_TYPE_STANDARD); + } else - { - unsigned int r_sym = elfcpp::elf_r_sym(rela.get_r_info()); - gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)); - got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD); - } - have_got_offset = true; + { + unsigned int r_sym = elfcpp::elf_r_sym(rela.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)); + got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD); + } break; // R_PPC_PLTREL24 is rather special. If non-zero, - // the addend specifies the GOT pointer offset within .got2. + // the addend specifies the GOT pointer offset within .got2. case elfcpp::R_PPC_PLTREL24: if (addend >= 32768) { @@ -1664,7 +1818,6 @@ Target_powerpc::Relocate::relocate( got2_offset = got2->offset(); addend += got2_offset; } - have_got_offset = true; break; default: @@ -1818,8 +1971,7 @@ Target_powerpc::Relocate::relocate_tls( section_size_type) { Output_segment* tls_segment = relinfo->layout->tls_segment(); - typedef Powerpc_relocate_functions Reloc; - const Sized_relobj* object = relinfo->object; + const Sized_relobj_file* object = relinfo->object; const elfcpp::Elf_Xword addend = rela.get_r_addend(); typename elfcpp::Elf_types::Elf_Addr value = psymval->value(object, 0); @@ -1893,7 +2045,7 @@ void Target_powerpc::scan_relocatable_relocs( Symbol_table* symtab, Layout* layout, - Sized_relobj* object, + Sized_relobj_file* object, unsigned int data_shndx, unsigned int sh_type, const unsigned char* prelocs, @@ -1979,12 +2131,16 @@ class Target_selector_powerpc : public Target_selector public: Target_selector_powerpc() : Target_selector(elfcpp::EM_NONE, size, big_endian, - (size == 64 ? - (big_endian ? "elf64-powerpc" : "elf64-powerpcle") : - (big_endian ? "elf32-powerpc" : "elf32-powerpcle"))) + (size == 64 + ? (big_endian ? "elf64-powerpc" : "elf64-powerpcle") + : (big_endian ? "elf32-powerpc" : "elf32-powerpcle")), + (size == 64 + ? (big_endian ? "elf64ppc" : "elf64lppc") + : (big_endian ? "elf32ppc" : "elf32lppc"))) { } - Target* do_recognize(int machine, int, int) + virtual Target* + do_recognize(Input_file*, off_t, int machine, int, int) { switch (size) { @@ -2005,7 +2161,8 @@ public: return this->instantiate_target(); } - Target* do_instantiate_target() + virtual Target* + do_instantiate_target() { return new Target_powerpc(); } };