This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gold][aarch64] PR gold/19163: zero-out ABS64/32/16/ in .rela.dyn.


Hi Cary, this is the patch to fix PR gold/19163 (and gold/19169).

Android bionic dynamic linker has bugs dealing with ABS64/32/16 in the
.rela.dyn section. It was fixed last week here -
https://android-review.googlesource.com/#/c/176902/2/linker/linker.cpp

The problem here is that that L and M release will still have this
bug. So here is the patch to zero out the relocation values in these
affected relocs (AARCH64_ABS64/32/16).

Tested - build O2/O0 on x86_64 machine. build O2 on aarch64 machine.
              passed gold dev unit test cases.
              manually checked the value in .rela.dyn, so that ABSxx
are all zero.
              manually verified case in PR gold/19169


Ok for trunk?

Thanks,
Han
diff --git a/gold/aarch64.cc b/gold/aarch64.cc
index 2e3c42a..78fd419 100644
--- a/gold/aarch64.cc
+++ b/gold/aarch64.cc
@@ -1766,10 +1766,23 @@ class AArch64_relobj : public Sized_relobj_file<size, big_endian>
     // The stubs have relocations and we need to process them after writing
     // out the stubs.  So relocation now must follow section write.
     this->set_relocs_must_follow_section_writes();
   }
 
+  // Record a .rela.dyn ABS64/32/16 reloc.
+  void
+  add_global_symbol_to_zero_out_list(
+    Symbol* gsym,
+    unsigned int shndx,
+    Output_section* output_section,
+    unsigned int r_type,
+    uint64_t r_offset)
+  {
+    struct ZeroOutRecord zr = {gsym, shndx, output_section, r_type, r_offset};
+    this->zero_out_list_.push_back(zr);
+  }
+
   // Structure for mapping symbol position.
   struct Mapping_symbol_position
   {
     Mapping_symbol_position(unsigned int shndx, AArch64_address offset):
       shndx_(shndx), offset_(offset)
@@ -1814,10 +1827,13 @@ class AArch64_relobj : public Sized_relobj_file<size, big_endian>
   virtual void
   do_count_local_symbols(Stringpool_template<char>*,
 			 Stringpool_template<char>*);
 
  private:
+  // Zero out .rela.dyn ABS64/32/16 (PR gold/19613 and gold/19619).
+  void zero_out_relocs(typename Sized_relobj_file<size, big_endian>::Views*);
+
   // Fix all errata in the object.
   void
   fix_errata(typename Sized_relobj_file<size, big_endian>::Views* pviews);
 
   // Try to fix erratum 843419 in an optimized way. Return true if patch is
@@ -1836,13 +1852,64 @@ class AArch64_relobj : public Sized_relobj_file<size, big_endian>
   // List of stub tables.
   Stub_table_list stub_tables_;
 
   // Mapping symbol information sorted by (section index, section_offset).
   Mapping_symbol_info mapping_symbol_info_;
+
+  // Struct that holds required information to do a zero-out action.
+  struct ZeroOutRecord
+  {
+    Symbol* gsym;
+    unsigned int shndx;
+    Output_section* output_section;
+    unsigned int r_type;
+    uint64_t r_offset;
+  };
+
+  // For PR gold/19163 (and gold/19169), we maintain a vector of ABS64/32/16
+  // relocs in the .rela.dyn section. We maintain such data structure because
+  // not all ABS64/32/16 need to be zero-out, we only change those that are put
+  // in .rela.dyn (that is - to be later handled by dynamic linker).
+  typedef std::vector<ZeroOutRecord> ZeroOutList;
+  typedef typename ZeroOutList::iterator ZeroOutIter;
+  ZeroOutList zero_out_list_;
 };  // End of AArch64_relobj
 
 
+// Zero out .rela.dyn ABS64/32/16 (PR gold/19613 and gold/19619).
+template<int size, bool big_endian>
+void
+AArch64_relobj<size, big_endian>::zero_out_relocs(
+  typename Sized_relobj_file<size, big_endian>::Views* pviews)
+{
+  typedef AArch64_relocate_functions<size, big_endian> Reloc;
+  for (ZeroOutIter p = this->zero_out_list_.begin(),
+	 end=this->zero_out_list_.end(); p != end; ++p)
+    {
+      Output_section* os = this->output_section(p->shndx);
+      gold_assert(os == p->output_section);
+      typename Sized_relobj_file<size, big_endian>::View_size&
+	os_view = (*pviews)[p->shndx];
+      unsigned char* reloc_view = os_view.view + p->r_offset;
+      switch (p->r_type)
+	{
+	case elfcpp::R_AARCH64_ABS64:
+	  Reloc::template zero_out<64>(reloc_view);
+	  break;
+	case elfcpp::R_AARCH64_ABS32:
+	  Reloc::template zero_out<32>(reloc_view);
+	  break;
+	case elfcpp::R_AARCH64_ABS16:
+	  Reloc::template zero_out<16>(reloc_view);
+	  break;
+	default:
+	  gold_unreachable();
+	}
+    }
+}
+
+
 // Override to record mapping symbol information.
 template<int size, bool big_endian>
 void
 AArch64_relobj<size, big_endian>::do_count_local_symbols(
     Stringpool_template<char>* pool, Stringpool_template<char>* dynpool)
@@ -2044,10 +2111,13 @@ AArch64_relobj<size, big_endian>::do_relocate_sections(
 {
   // Call parent to relocate sections.
   Sized_relobj_file<size, big_endian>::do_relocate_sections(symtab, layout,
 							    pshdrs, of, pviews);
 
+  // Zero out .rela.dyn ABS64/32/16 (PR gold/19613 and gold/19619).
+  this->zero_out_relocs(pviews);
+
   // We do not generate stubs if doing a relocatable link.
   if (parameters->options().relocatable())
     return;
 
   if (parameters->options().fix_cortex_a53_843419()
@@ -5130,10 +5200,21 @@ class AArch64_relocate_functions
   {
     update_view_two_parts<32>(view, 0x05, (branch_offset >> 2),
 			      26, 0, 0xffffffff);
   }
 
+  // Zero out the view.
+  template<int valsize>
+  static inline void
+  zero_out(unsigned char* view)
+  {
+    typedef typename elfcpp::Swap_unaligned<valsize, big_endian>::Valtype
+      Valtype;
+    elfcpp::Swap_unaligned<valsize, big_endian>::writeval(view,
+      static_cast<Valtype>(0));
+  }
+
   // Do a simple rela relocation at unaligned addresses.
 
   template<int valsize>
   static inline typename This::Status
   rela_ua(unsigned char* view,
@@ -6245,11 +6326,17 @@ Target_aarch64<size, big_endian>::Scan::global(
 		check_non_pic(object, r_type);
 		Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>*
 		    rela_dyn = target->rela_dyn_section(layout);
 		rela_dyn->add_global(
 		  gsym, r_type, output_section, object,
-		  data_shndx, rela.get_r_offset(),rela.get_r_addend());
+		  data_shndx, rela.get_r_offset(), rela.get_r_addend());
+		The_aarch64_relobj* aarch64_relobj =
+		  static_cast<AArch64_relobj<size, big_endian> *>(object);
+		// Record a .rela.dyn ABS64/32/16 reloc.
+		aarch64_relobj->add_global_symbol_to_zero_out_list(
+		  gsym, data_shndx, output_section, r_type,
+		  rela.get_r_offset());
 	      }
 	  }
       }
       break;
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]