Skip to content

Commit

Permalink
Merging r312706:
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
r312706 | anng | 2017-09-07 01:43:56 -0700 (Thu, 07 Sep 2017) | 14 lines

[LLD] Fix padding of .eh_frame when in executable segment

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: 314861
  • Loading branch information
rui314 committed Oct 3, 2017
1 parent a4fcc49 commit 08de6a4
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 08de6a4

Please sign in to comment.