Skip to content

Commit

Permalink
[LLD] Fix padding of .eh_frame when in executable segment
Browse files Browse the repository at this point in the history
The default padding for an executable segment is the target trap
instruction which for x86_64 is 0xCC. However, the .eh_frame section
requires the padding to be zero. The code that writes the .eh_frame
section assumes that its segment is zero initialized and does not
explicitly write the zero padding. This does not work when the .eh_frame
section is in the executable segment (for example when using
-no-rosegment).

This patch changes the .eh_frame writing code to explicitly write the
zero padding.

Differential Revision: https://reviews.llvm.org/D37462

llvm-svn: 312706
  • Loading branch information
nga888 committed Sep 7, 2017
1 parent 7594c61 commit 6dee736
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 1 deletion.
7 changes: 6 additions & 1 deletion lld/ELF/SyntheticSections.cpp
Expand Up @@ -523,9 +523,14 @@ template <class ELFT>
static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {
memcpy(Buf, D.data(), D.size());

size_t Aligned = alignTo(D.size(), sizeof(typename ELFT::uint));

// Zero-clear trailing padding if it exists.
memset(Buf + D.size(), 0, Aligned - D.size());

// Fix the size field. -4 since size does not include the size field itself.
const endianness E = ELFT::TargetEndianness;
write32<E>(Buf, alignTo(D.size(), sizeof(typename ELFT::uint)) - 4);
write32<E>(Buf, Aligned - 4);
}

template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() {
Expand Down
64 changes: 64 additions & 0 deletions lld/test/ELF/eh-frame-padding-no-rosegment.s
@@ -0,0 +1,64 @@
// REQUIRES: x86

.cfi_startproc
.cfi_personality 0x1b, bar
.cfi_endproc

.global bar
.hidden bar
bar:

// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o

// Check the size of the CIE (0x18 + 4) and FDE (0x10 + 4)
// RUN: llvm-readobj -s -section-data %t.o | FileCheck --check-prefix=OBJ %s

// OBJ: Name: .eh_frame
// OBJ-NEXT: Type:
// OBJ-NEXT: Flags [
// OBJ-NEXT: SHF_ALLOC
// OBJ-NEXT: ]
// OBJ-NEXT: Address:
// OBJ-NEXT: Offset:
// OBJ-NEXT: Size:
// OBJ-NEXT: Link:
// OBJ-NEXT: Info:
// OBJ-NEXT: AddressAlignment:
// OBJ-NEXT: EntrySize:
// OBJ-NEXT: SectionData (
// OBJ-NEXT: 0000: 18000000 00000000 017A5052 00017810
// OBJ-NEXT: 0010: 061B0000 00001B0C 07089001 10000000
// OBJ-NEXT: 0020: 20000000 00000000 00000000 00000000
// OBJ-NEXT: )

// RUN: ld.lld %t.o -no-rosegment -o %t -shared

// Check that .eh_frame is in the same segment as .text
// RUN: llvm-readobj -l --elf-output-style=GNU %t | FileCheck --check-prefix=PHDR %s

// PHDR: Segment Sections
// PHDR: .text
// PHDR-SAME: .eh_frame

// Check that the CIE and FDE are padded with 0x00 and not 0xCC when the
// .eh_frame section is placed in the executable segment
// RUN: llvm-readobj -s -section-data %t | FileCheck %s

// CHECK: Name: .eh_frame
// CHECK-NEXT: Type:
// CHECK-NEXT: Flags
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: ]
// CHECK-NEXT: Address:
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size:
// CHECK-NEXT: Link:
// CHECK-NEXT: Info:
// CHECK-NEXT: AddressAlignment:
// CHECK-NEXT: EntrySize:
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 1C000000 00000000 017A5052 00017810
// CHECK-NEXT: 0010: 061BBEFF FFFF1B0C 07089001 00000000
// CHECK-NEXT: 0020: 14000000 24000000 A8FFFFFF 00000000
// CHECK-NEXT: 0030: 00000000 00000000
// CHECK-NEXT: )

0 comments on commit 6dee736

Please sign in to comment.