From 0b213c9090369ff43060816aed38cb6c67e228f8 Mon Sep 17 00:00:00 2001 From: Maksim Panchenko Date: Mon, 3 Oct 2022 18:50:18 -0700 Subject: [PATCH] [BOLT] Fix writing out unmarked .eh_frame section When BOLT updates .eh_frame section, it concatenates newly-generated contents (from CFI directives) with the original .eh_frame that has relocations applied to it. However, if no new content is generated, the original .eh_frame has to be left intact. In that case, BOLT was still writing out the relocatable copy of the original .eh_frame section to the new segment, even though this copy was never used and was not even marked in the section header table. Detect the scenario above and skip allocating extra space for .eh_frame. Reviewed By: rafauler Differential Revision: https://reviews.llvm.org/D135223 --- bolt/lib/Rewrite/RewriteInstance.cpp | 10 ++++++++++ bolt/test/X86/dummy-eh-frame-bug.s | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 bolt/test/X86/dummy-eh-frame-bug.s diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 16e2db8269eeb..53ce8d1d68538 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -3798,6 +3798,16 @@ void RewriteInstance::mapDataSections(RuntimeDyld &RTDyld) { if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary()) RtLibrary->addRuntimeLibSections(Sections); + if (!EHFrameSection || !EHFrameSection->isFinalized()) { + ErrorOr OldEHFrameSection = + BC->getUniqueSectionByName(Twine(getOrgSecPrefix(), ".eh_frame").str()); + if (OldEHFrameSection) { + RTDyld.reassignSectionAddress(OldEHFrameSection->getSectionID(), + NextAvailableAddress); + BC->deregisterSection(*OldEHFrameSection); + } + } + for (std::string &SectionName : Sections) { ErrorOr Section = BC->getUniqueSectionByName(SectionName); if (!Section || !Section->isAllocatable() || !Section->isFinalized()) diff --git a/bolt/test/X86/dummy-eh-frame-bug.s b/bolt/test/X86/dummy-eh-frame-bug.s new file mode 100644 index 0000000000000..2d05cf3d88d78 --- /dev/null +++ b/bolt/test/X86/dummy-eh-frame-bug.s @@ -0,0 +1,27 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld %t.o -o %t.exe -q +# RUN: llvm-bolt %t.exe -o %t.bolt.exe --funcs=nocfi_function +# RUN: llvm-readelf --section-headers %t.bolt.exe | FileCheck %s + +## Check that llvm-bolt does not allocate unmarked space for original .eh_frame +## after .text when no update is needed to .eh_frame. + +# CHECK: {{ .text}} PROGBITS [[#%x,ADDR:]] [[#%x,OFFSET:]] [[#%x,SIZE:]] +# CHECK-NEXT: 0000000000000000 [[#%x, OFFSET + SIZE]] + + .text + .globl nocfi_function + .type nocfi_function,@function +nocfi_function: + ret + .size nocfi_function, .-nocfi_function + + .globl _start + .type _start,@function +_start: + .cfi_startproc + call nocfi_function + .size _start, .-_start + .cfi_endproc