Fix ehframe header handling for shared libraries.

This commit is contained in:
Ian Lance Taylor 2007-12-07 06:44:01 +00:00
parent a20d5e98e5
commit 4117d76827
3 changed files with 30 additions and 5 deletions

View File

@ -234,8 +234,11 @@ Eh_frame_hdr::do_sized_write(Output_file* of)
template<int size, bool big_endian>
typename elfcpp::Elf_types<size>::Elf_Addr
Eh_frame_hdr::get_fde_pc(const unsigned char* eh_frame_contents,
off_t fde_offset, unsigned char fde_encoding)
Eh_frame_hdr::get_fde_pc(
typename elfcpp::Elf_types<size>::Elf_Addr eh_frame_address,
const unsigned char* eh_frame_contents,
off_t fde_offset,
unsigned char fde_encoding)
{
// The FDE starts with a 4 byte length and a 4 byte offset to the
// CIE. The PC follows.
@ -274,6 +277,22 @@ Eh_frame_hdr::get_fde_pc(const unsigned char* eh_frame_contents,
break;
default:
// All other cases were rejected in Eh_frame::read_cie.
gold_unreachable();
}
switch (fde_encoding & 0xf0)
{
case 0:
break;
case elfcpp::DW_EH_PE_pcrel:
pc += eh_frame_address + fde_offset + 8;
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();
}
@ -304,7 +323,8 @@ Eh_frame_hdr::get_fde_addresses(Output_file* of,
++p)
{
typename elfcpp::Elf_types<size>::Elf_Addr fde_pc;
fde_pc = this->get_fde_pc<size, big_endian>(eh_frame_contents,
fde_pc = this->get_fde_pc<size, big_endian>(eh_frame_address,
eh_frame_contents,
p->first, p->second);
fde_addresses->push_back(fde_pc, eh_frame_address + p->first);
}
@ -742,6 +762,8 @@ Eh_frame::read_cie(Sized_relobj<size, big_endian>* object,
case elfcpp::DW_EH_PE_udata8:
break;
default:
// We don't expect to see any other cases here, and
// we're not prepared to handle them.
return false;
}
++p;

View File

@ -131,7 +131,8 @@ class Eh_frame_hdr : public Output_section_data
// Return the PC to which an FDE refers.
template<int size, bool big_endian>
typename elfcpp::Elf_types<size>::Elf_Addr
get_fde_pc(const unsigned char* eh_frame_contents,
get_fde_pc(typename elfcpp::Elf_types<size>::Elf_Addr eh_frame_address,
const unsigned char* eh_frame_contents,
off_t fde_offset, unsigned char fde_encoding);
// Convert Fde_offsets to Fde_addresses.

View File

@ -992,7 +992,9 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
// Find the PT_LOAD segments, and set their addresses and offsets
// and their section's addresses and offsets.
uint64_t addr;
if (options_.user_set_text_segment_address())
if (parameters->output_is_shared())
addr = 0;
else if (options_.user_set_text_segment_address())
addr = options_.text_segment_address();
else
addr = target->default_text_segment_address();