Skip to content

Commit 0977a71

Browse files
authored
[BOLT] Skip FDE emission for patch functions (#136224)
Patch functions are used to fix instructions in the original code, i.e., they are not functions in a traditional sense, but rather pieces of emitted code that are embedded into real functions. We used to emit FDEs for all functions, including patch functions. However, FDEs for patches are not only unnecessary, but they can lead to problems with libraries and runtimes that consume FDEs, e.g. C++ exception handling runtime. Note that we use named patches to fix function entry points and in that case they behave more like regular functions. Thus we issue FDEs for those.
1 parent e5263e3 commit 0977a71

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

bolt/lib/Core/BinaryEmitter.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,10 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
373373
Streamer.emitLabel(StartSymbol);
374374
}
375375

376+
const bool NeedsFDE =
377+
Function.hasCFI() && !(Function.isPatch() && Function.isAnonymous());
376378
// Emit CFI start
377-
if (Function.hasCFI()) {
379+
if (NeedsFDE) {
378380
Streamer.emitCFIStartProc(/*IsSimple=*/false);
379381
if (Function.getPersonalityFunction() != nullptr)
380382
Streamer.emitCFIPersonality(Function.getPersonalityFunction(),
@@ -421,7 +423,7 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
421423
Streamer.emitBytes(BC.MIB->getTrapFillValue());
422424

423425
// Emit CFI end
424-
if (Function.hasCFI())
426+
if (NeedsFDE)
425427
Streamer.emitCFIEndProc();
426428

427429
MCSymbol *EndSymbol = Function.getFunctionEndLabel(FF.getFragmentNum());

bolt/test/AArch64/lite-mode.s

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
# RUN: llvm-objdump -d --disassemble-symbols=cold_function %t.bolt \
1212
# RUN: | FileCheck %s
1313

14+
15+
## Verify that the number of FDEs matches the number of functions in the output
16+
## binary. There are three original functions and two optimized.
17+
# RUN: llvm-readelf -u %t.bolt | grep -wc FDE \
18+
# RUN: | FileCheck --check-prefix=CHECK-FDE %s
19+
# CHECK-FDE: 5
20+
1421
## In lite mode, optimized code will be separated from the original .text by
1522
## over 128MB, making it impossible for call/bl instructions in cold functions
1623
## to reach optimized functions directly.

0 commit comments

Comments
 (0)