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.
This commit is contained in:
parent
3f26b7e8cb
commit
02d7cd4495
5 changed files with 69 additions and 1 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
19
gold/i386.cc
19
gold/i386.cc
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue