[ELF] Use pcrel format for eh_frame_ptr field encoding
The `eh_frame_ptr` field in the `.eh_frame_hdr` section contains an address of the `.eh_frame` section. Using an absolute 32-bit format for encoding of this field does not work for 64-bit targets. It is better to use a relative format because it covers both 32-bit and 64-bit cases. Sure this work if a distance between `.eh_frame_hdr` and `.eh_frame` sections is less than 4 Gb but it is a rather correct assumption. http://reviews.llvm.org/D8352 llvm-svn: 232414
This commit is contained in:
parent
9255a5535a
commit
4b4706b601
|
@ -1450,7 +1450,8 @@ template <class ELFT> class EHFrameHeader : public Section<ELFT> {
|
|||
public:
|
||||
EHFrameHeader(const ELFLinkingContext &context, StringRef name,
|
||||
TargetLayout<ELFT> &layout, int32_t order)
|
||||
: Section<ELFT>(context, name, "EHFrameHeader"), _layout(layout) {
|
||||
: Section<ELFT>(context, name, "EHFrameHeader"), _ehFrameOffset(0),
|
||||
_layout(layout) {
|
||||
this->setOrder(order);
|
||||
this->_entSize = 0;
|
||||
this->_type = SHT_PROGBITS;
|
||||
|
@ -1467,24 +1468,27 @@ public:
|
|||
|
||||
void finalize() override {
|
||||
OutputSection<ELFT> *s = _layout.findOutputSection(".eh_frame");
|
||||
_ehFrameAddr = s ? s->virtualAddr() : 0;
|
||||
OutputSection<ELFT> *h = _layout.findOutputSection(".eh_frame_hdr");
|
||||
if (s && h)
|
||||
_ehFrameOffset = s->virtualAddr() - (h->virtualAddr() + 4);
|
||||
}
|
||||
|
||||
virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
|
||||
llvm::FileOutputBuffer &buffer) override {
|
||||
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
|
||||
llvm::FileOutputBuffer &buffer) override {
|
||||
uint8_t *chunkBuffer = buffer.getBufferStart();
|
||||
uint8_t *dest = chunkBuffer + this->fileOffset();
|
||||
int pos = 0;
|
||||
dest[pos++] = 1; // version
|
||||
dest[pos++] = llvm::dwarf::DW_EH_PE_udata4; // eh_frame_ptr_enc
|
||||
dest[pos++] = llvm::dwarf::DW_EH_PE_pcrel |
|
||||
llvm::dwarf::DW_EH_PE_sdata4; // eh_frame_ptr_enc
|
||||
dest[pos++] = llvm::dwarf::DW_EH_PE_omit; // fde_count_enc
|
||||
dest[pos++] = llvm::dwarf::DW_EH_PE_omit; // table_enc
|
||||
*reinterpret_cast<typename llvm::object::ELFFile<ELFT>::Elf_Word *>(
|
||||
dest + pos) = (uint32_t)_ehFrameAddr;
|
||||
*reinterpret_cast<typename llvm::object::ELFFile<ELFT>::Elf_Sword *>(
|
||||
dest + pos) = _ehFrameOffset;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t _ehFrameAddr;
|
||||
int32_t _ehFrameOffset;
|
||||
TargetLayout<ELFT> &_layout;
|
||||
};
|
||||
} // end namespace elf
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#RUN: yaml2obj -format=elf %s > %t
|
||||
#RUN: lld -flavor gnu -target x86_64-linux %t --noinhibit-exec \
|
||||
#RUN: -o %t1
|
||||
#RUN: llvm-readobj -s %t1 | FileCheck %s
|
||||
#RUN: llvm-objdump -s %t1 | FileCheck %s
|
||||
|
||||
!ELF
|
||||
FileHeader:
|
||||
|
@ -23,4 +23,8 @@ Symbols:
|
|||
Type: STT_SECTION
|
||||
Section: .eh_frame
|
||||
|
||||
#CHECK: .eh_frame_hdr
|
||||
# CHECK: Contents of section .eh_frame:
|
||||
# CHECK-NEXT: 4001e0 00
|
||||
# CHECK-NEXT: Contents of section .eh_frame_hdr:
|
||||
# CHECK-NEXT: 4001e8 011bffff f4ffffff
|
||||
# ^ 0x4001e0 - 0x4001e8 - 4 = 0xfffffff4
|
||||
|
|
Loading…
Reference in New Issue