PR gold/12525
authorIan Lance Taylor <ian@airs.com>
Sat, 2 Jul 2011 00:03:25 +0000 (00:03 +0000)
committerIan Lance Taylor <ian@airs.com>
Sat, 2 Jul 2011 00:03:25 +0000 (00:03 +0000)
* ehframe.cc (Eh_frame_hdr::get_fde_pc): Handle DW_EH_PE_datarel.
Assert if we see DW_EH_PE_indirect.
* target.h (Target::ehframe_datarel_base): New function.
(Target::do_ehframe_datarel_base): New target function.
* i386.cc (Target_i386::do_ehframe_datarel_base): New function.
* x86_64.cc (Target_x86_64::do_ehframe_datarel_base): New
function.

gold/ChangeLog
gold/ehframe.cc
gold/i386.cc
gold/target.h
gold/x86_64.cc

index 8b8112dc320458ca46dabcd7343de485d2d9ecf4..ae36ea22a1a8b20875270b64cebf09952f1bcb4c 100644 (file)
@@ -1,3 +1,14 @@
+2011-07-01  Ian Lance Taylor  <iant@google.com>
+
+       PR gold/12525
+       * ehframe.cc (Eh_frame_hdr::get_fde_pc): Handle DW_EH_PE_datarel.
+       Assert if we see DW_EH_PE_indirect.
+       * target.h (Target::ehframe_datarel_base): New function.
+       (Target::do_ehframe_datarel_base): New target function.
+       * i386.cc (Target_i386::do_ehframe_datarel_base): New function.
+       * x86_64.cc (Target_x86_64::do_ehframe_datarel_base): New
+       function.
+
 2011-07-01  Ian Lance Taylor  <iant@google.com>
 
        PR gold/12571
index 80b00358d22ca84c312d820240bfbb0e092f46b7..dad23319913d836a0d98b6528c335ef045e56238 100644 (file)
@@ -266,7 +266,7 @@ Eh_frame_hdr::get_fde_pc(
       gold_unreachable();
     }
 
-  switch (fde_encoding & 0xf0)
+  switch (fde_encoding & 0x70)
     {
     case 0:
       break;
@@ -275,12 +275,18 @@ Eh_frame_hdr::get_fde_pc(
       pc += eh_frame_address + fde_offset + 8;
       break;
 
+    case elfcpp::DW_EH_PE_datarel:
+      pc += parameters->target().ehframe_datarel_base();
+      break;
+
     default:
       // If other cases arise, then we have to handle them, or we have
       // to reject them by returning false in Eh_frame::read_cie.
       gold_unreachable();
     }
 
+  gold_assert((fde_encoding & elfcpp::DW_EH_PE_indirect) == 0);
+
   return pc;
 }
 
index 6bec81f0507cc4629caf0b12fd841835a52649e5..65ff05f5f56a3c9c03c848239a0f423c106ea9fc 100644 (file)
@@ -295,6 +295,10 @@ class Target_i386 : public Sized_target<32, false>
   do_can_check_for_function_pointers() const
   { return true; }
 
+  // Return the base for a DW_EH_PE_datarel encoding.
+  uint64_t
+  do_ehframe_datarel_base() const;
+
   // Return whether SYM is call to a non-split function.
   bool
   do_is_call_to_non_split(const Symbol* sym, unsigned int) const;
@@ -3267,6 +3271,21 @@ Target_i386::do_code_fill(section_size_type length) const
   return std::string(nops[length], length);
 }
 
+// Return the value to use for the base of a DW_EH_PE_datarel offset
+// in an FDE.  Solaris and SVR4 use DW_EH_PE_datarel because their
+// assembler can not write out the difference between two labels in
+// different sections, so instead of using a pc-relative value they
+// use an offset from the GOT.
+
+uint64_t
+Target_i386::do_ehframe_datarel_base() const
+{
+  gold_assert(this->global_offset_table_ != NULL);
+  Symbol* sym = this->global_offset_table_;
+  Sized_symbol<32>* ssym = static_cast<Sized_symbol<32>*>(sym);
+  return ssym->value();
+}
+
 // Return whether SYM should be treated as a call to a non-split
 // function.  We don't want that to be true of a call to a
 // get_pc_thunk function.
index f9b8c0459294f43be56c34764ef6e8ff9c34782d..c2ccc638c94bfc38c916155830555034bde0e3d9 100644 (file)
@@ -276,6 +276,15 @@ class Target
   section_may_have_icf_unsafe_pointers(const char* section_name) const
   { return this->do_section_may_have_icf_unsafe_pointers(section_name); }
 
+  // Return the base to use for the PC value in an FDE when it is
+  // encoded using DW_EH_PE_datarel.  This does not appear to be
+  // documented anywhere, but it is target specific.  Any use of
+  // DW_EH_PE_datarel in gcc requires defining a special macro
+  // (ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX) to output the value.
+  uint64_t
+  ehframe_datarel_base() const
+  { return this->do_ehframe_datarel_base(); }
+
   // Return true if a reference to SYM from a reloc of type R_TYPE
   // means that the current function may call an object compiled
   // without -fsplit-stack.  SYM is known to be defined in an object
@@ -521,6 +530,10 @@ class Target
            && !is_prefix_of(".eh_frame", section_name));
   }
 
+  virtual uint64_t
+  do_ehframe_datarel_base() const
+  { gold_unreachable(); }
+
   // Virtual function which may be overridden by the child class.  The
   // default implementation is that any function not defined by the
   // ABI is a call to a non-split function.
index 12a5467f3f55e206393cc7d6a1155874e4f1c84c..8308bf4ba7a52340e06d1f40fe71c7c63d09e1b2 100644 (file)
@@ -350,6 +350,10 @@ class Target_x86_64 : public Sized_target<64, false>
   do_can_check_for_function_pointers() const
   { return !parameters->options().pie(); }
 
+  // Return the base for a DW_EH_PE_datarel encoding.
+  uint64_t
+  do_ehframe_datarel_base() const;
+
   // Adjust -fsplit-stack code which calls non-split-stack code.
   void
   do_calls_non_split(Relobj* object, unsigned int shndx,
@@ -3640,6 +3644,21 @@ Target_x86_64::do_reloc_addend(void* arg, unsigned int r_type,
   return psymval->value(ti.object, 0);
 }
 
+// Return the value to use for the base of a DW_EH_PE_datarel offset
+// in an FDE.  Solaris and SVR4 use DW_EH_PE_datarel because their
+// assembler can not write out the difference between two labels in
+// different sections, so instead of using a pc-relative value they
+// use an offset from the GOT.
+
+uint64_t
+Target_x86_64::do_ehframe_datarel_base() const
+{
+  gold_assert(this->global_offset_table_ != NULL);
+  Symbol* sym = this->global_offset_table_;
+  Sized_symbol<64>* ssym = static_cast<Sized_symbol<64>*>(sym);
+  return ssym->value();
+}
+
 // FNOFFSET in section SHNDX in OBJECT is the start of a function
 // compiled with -fsplit-stack.  The function calls non-split-stack
 // code.  We have to change the function so that it always ensures