mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-29 00:21:14 +00:00
[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
This commit is contained in:
parent
f1848b0a0e
commit
553c238952
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>(
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
41
bolt/test/runtime/exceptions-no-pie.cpp
Normal file
41
bolt/test/runtime/exceptions-no-pie.cpp
Normal file
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user