diff options
author | Ian Lance Taylor <iant@google.com> | 2007-12-07 06:44:01 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2007-12-07 06:44:01 +0000 |
commit | 4117d76827b3768e9da6ef52f52a59c5ae92bed3 (patch) | |
tree | 0e922a8a56fb517fce40ab926e9d1bb98039818a /gold | |
parent | a20d5e98e51d91b66dfccc205d4d27e8850238b2 (diff) | |
download | gdb-4117d76827b3768e9da6ef52f52a59c5ae92bed3.zip gdb-4117d76827b3768e9da6ef52f52a59c5ae92bed3.tar.gz gdb-4117d76827b3768e9da6ef52f52a59c5ae92bed3.tar.bz2 |
Fix ehframe header handling for shared libraries.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ehframe.cc | 28 | ||||
-rw-r--r-- | gold/ehframe.h | 3 | ||||
-rw-r--r-- | gold/layout.cc | 4 |
3 files changed, 30 insertions, 5 deletions
diff --git a/gold/ehframe.cc b/gold/ehframe.cc index 91a977f..328048b 100644 --- a/gold/ehframe.cc +++ b/gold/ehframe.cc @@ -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; diff --git a/gold/ehframe.h b/gold/ehframe.h index 12c8c16..5a733e7 100644 --- a/gold/ehframe.h +++ b/gold/ehframe.h @@ -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. diff --git a/gold/layout.cc b/gold/layout.cc index 68ebc6b..f5a1f67 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -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(); |