diff options
author | revunov.denis@huawei.com <revunov.denis@huawei-partners.com> | 2022-09-14 16:29:48 +0000 |
---|---|---|
committer | revunov.denis@huawei.com <revunov.denis@huawei-partners.com> | 2022-09-14 16:33:47 +0000 |
commit | 553c23895217cfe24404a50dede2416c9e1a3a5e (patch) | |
tree | 9d5dc309e7825e7495181c8684518fe459044c98 /bolt | |
parent | f1848b0a0ed70fc91eff50f6c47561ca24362a37 (diff) | |
download | llvm-553c23895217cfe24404a50dede2416c9e1a3a5e.zip llvm-553c23895217cfe24404a50dede2416c9e1a3a5e.tar.gz llvm-553c23895217cfe24404a50dede2416c9e1a3a5e.tar.bz2 |
[BOLT] Preserve original LSDA type encoding
In non-pie binaries BOLT unconditionally converted type encoding
from indirect to absptr, which broke std exceptions since pointers
to their typeinfo were only assigned at runtime in .data section.
In this patch we preserve original encoding so that indirect
remains indirect and can be resolved at runtime, and absolute remains absolute.
Reviewed By: rafauler, maksfb
Differential Revision: https://reviews.llvm.org/D132484
Diffstat (limited to 'bolt')
-rw-r--r-- | bolt/include/bolt/Core/BinaryContext.h | 3 | ||||
-rw-r--r-- | bolt/include/bolt/Core/BinaryFunction.h | 5 | ||||
-rw-r--r-- | bolt/lib/Core/BinaryContext.cpp | 5 | ||||
-rw-r--r-- | bolt/lib/Core/BinaryEmitter.cpp | 11 | ||||
-rw-r--r-- | bolt/lib/Core/Exceptions.cpp | 1 | ||||
-rw-r--r-- | bolt/test/runtime/exceptions-no-pie.cpp | 41 |
6 files changed, 55 insertions, 11 deletions
diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index 41e6e5c..02af0a1 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -388,6 +388,8 @@ public: } unsigned getDWARFEncodingSize(unsigned Encoding) { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; switch (Encoding & 0x0f) { default: llvm_unreachable("unknown encoding"); @@ -671,7 +673,6 @@ public: /// DWARF encoding. Available encoding types defined in BinaryFormat/Dwarf.h /// enum Constants, e.g. DW_EH_PE_omit. - unsigned TTypeEncoding = dwarf::DW_EH_PE_omit; unsigned LSDAEncoding = dwarf::DW_EH_PE_omit; BinaryContext(std::unique_ptr<MCContext> Ctx, diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index 88b500e..36996ae 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -388,6 +388,9 @@ private: /// Original LSDA address for the function. uint64_t LSDAAddress{0}; + /// Original LSDA type encoding + unsigned LSDATypeEncoding{dwarf::DW_EH_PE_omit}; + /// Containing compilation unit for the function. DWARFUnit *DwarfUnit{nullptr}; @@ -1438,6 +1441,8 @@ public: const LSDATypeTableTy &getLSDATypeTable() const { return LSDATypeTable; } + unsigned getLSDATypeEncoding() const { return LSDATypeEncoding; } + const LSDATypeTableTy &getLSDATypeAddressTable() const { return LSDATypeAddressTable; } diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index 1c4c53c..a79d16e 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -186,13 +186,9 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, Large = true; unsigned LSDAEncoding = Large ? dwarf::DW_EH_PE_absptr : dwarf::DW_EH_PE_udata4; - unsigned TTypeEncoding = - Large ? dwarf::DW_EH_PE_absptr : dwarf::DW_EH_PE_udata4; if (IsPIC) { LSDAEncoding = dwarf::DW_EH_PE_pcrel | (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4); - TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | - (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4); } std::unique_ptr<MCDisassembler> DisAsm( @@ -236,7 +232,6 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, std::move(InstructionPrinter), std::move(MIA), nullptr, std::move(MRI), std::move(DisAsm)); - BC->TTypeEncoding = TTypeEncoding; BC->LSDAEncoding = LSDAEncoding; BC->MAB = std::unique_ptr<MCAsmBackend>( diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp index 5927269..bc5bcad 100644 --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -897,7 +897,7 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) { Streamer.switchSection(BC.MOFI->getLSDASection()); - const unsigned TTypeEncoding = BC.TTypeEncoding; + const unsigned TTypeEncoding = BF.getLSDATypeEncoding(); const unsigned TTypeEncodingSize = BC.getDWARFEncodingSize(TTypeEncoding); const uint16_t TTypeAlignment = 4; @@ -971,10 +971,11 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) { TTypeBaseOffset; // TType base offset unsigned SizeAlign = (4 - TotalSize) & 3; - // Account for any extra padding that will be added to the call site table - // length. - Streamer.emitULEB128IntValue(TTypeBaseOffset, - /*PadTo=*/TTypeBaseOffsetSize + SizeAlign); + if (TTypeEncoding != dwarf::DW_EH_PE_omit) + // Account for any extra padding that will be added to the call site table + // length. + Streamer.emitULEB128IntValue(TTypeBaseOffset, + /*PadTo=*/TTypeBaseOffsetSize + SizeAlign); // Emit the landing pad call site table. We use signed data4 since we can emit // a landing pad in a different part of the split function that could appear diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp index 10a2c4b..b7ba53e 100644 --- a/bolt/lib/Core/Exceptions.cpp +++ b/bolt/lib/Core/Exceptions.cpp @@ -121,6 +121,7 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData, : *MaybeLPStart - Address; const uint8_t TTypeEncoding = Data.getU8(&Offset); + LSDATypeEncoding = TTypeEncoding; size_t TTypeEncodingSize = 0; uintptr_t TTypeEnd = 0; if (TTypeEncoding != DW_EH_PE_omit) { diff --git a/bolt/test/runtime/exceptions-no-pie.cpp b/bolt/test/runtime/exceptions-no-pie.cpp new file mode 100644 index 0000000..0c0df04 --- /dev/null +++ b/bolt/test/runtime/exceptions-no-pie.cpp @@ -0,0 +1,41 @@ +// REQUIRES: system-linux +// RUN: %clangxx -no-pie -Wl,-q %s -o %t.exe +// RUN: llvm-bolt %t.exe -o %t.bolt.exe -lite=false +// RUN: not --crash %t.bolt.exe 2>&1 | FileCheck %s --check-prefix=CHECK-FAIL +// CHECK-FAIL: Should pass one argument +// RUN: not %t.bolt.exe -1 | FileCheck %s --check-prefix=CHECK-BAD +// CHECK-BAD: Bad value +// RUN: not %t.bolt.exe 0 | FileCheck %s --check-prefix=CHECK-ZERO +// CHECK-ZERO: Value is zero +// RUN: %t.bolt.exe 1 | FileCheck %s --check-prefix=CHECK-GOOD +// CHECK-GOOD: Good value +#include <exception> +#include <iostream> + +struct ValIsZero { + const char *error = "Value is zero\n"; +}; +int dummy(int arg) { + if (arg == 0) + throw ValIsZero(); + if (arg > 0) + return 0; + else + throw std::out_of_range("Bad value"); +} + +int main(int argc, char **argv) { + if (argc != 2) + throw std::invalid_argument("Should pass one argument"); + try { + dummy(std::strtol(argv[1], nullptr, 10)); + } catch (std::out_of_range &e) { + std::cout << e.what() << "\n"; + return 1; + } catch (ValIsZero &e) { + std::cout << e.error; + return 1; + } + std::cout << "Good value\n"; + return 0; +} |