aboutsummaryrefslogtreecommitdiff
path: root/bolt
diff options
context:
space:
mode:
authorrevunov.denis@huawei.com <revunov.denis@huawei-partners.com>2022-09-14 16:29:48 +0000
committerrevunov.denis@huawei.com <revunov.denis@huawei-partners.com>2022-09-14 16:33:47 +0000
commit553c23895217cfe24404a50dede2416c9e1a3a5e (patch)
tree9d5dc309e7825e7495181c8684518fe459044c98 /bolt
parentf1848b0a0ed70fc91eff50f6c47561ca24362a37 (diff)
downloadllvm-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.h3
-rw-r--r--bolt/include/bolt/Core/BinaryFunction.h5
-rw-r--r--bolt/lib/Core/BinaryContext.cpp5
-rw-r--r--bolt/lib/Core/BinaryEmitter.cpp11
-rw-r--r--bolt/lib/Core/Exceptions.cpp1
-rw-r--r--bolt/test/runtime/exceptions-no-pie.cpp41
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;
+}