diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -383,6 +383,8 @@ } unsigned getDWARFEncodingSize(unsigned Encoding) { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; switch (Encoding & 0x0f) { default: llvm_unreachable("unknown encoding"); @@ -666,7 +668,6 @@ /// 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 Ctx, diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -393,6 +393,9 @@ /// 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}; @@ -1435,6 +1438,8 @@ 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 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -186,13 +186,9 @@ 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 DisAsm( @@ -236,7 +232,6 @@ std::move(InstructionPrinter), std::move(MIA), nullptr, std::move(MRI), std::move(DisAsm)); - BC->TTypeEncoding = TTypeEncoding; BC->LSDAEncoding = LSDAEncoding; BC->MAB = std::unique_ptr( diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -900,7 +900,7 @@ 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; @@ -977,10 +977,11 @@ 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 --- a/bolt/lib/Core/Exceptions.cpp +++ b/bolt/lib/Core/Exceptions.cpp @@ -121,6 +121,7 @@ : *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 --- /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 +#include + +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; +}