Fix SEH table addresses for Windows
Issue Details: The addresses for SEH tables for Windows are incorrect as 1 was unconditionally being added to all addresses. +1 is required for the SEH end address (as it is exclusive), but the SEH start addresses is inclusive and so should be used as-is. In the IP2State tables, the addresses are +1 for AMD64 to handle the return address for a call being after the actual call instruction but are as-is for ARM and ARM64 as the `StateFromIp` function in the VC runtime automatically takes this into account and adjusts the address that is it looking up. Fix Details: * Split the `getLabel` function into two: `getLabel` (used for the SEH start address and ARM+ARM64 IP2State addresses) and `getLabelPlusOne` (for the SEH end address, and AMD64 IP2State addresses). Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D107784
This commit is contained in:
parent
10020d41ee
commit
8ecce69594
|
@ -43,6 +43,7 @@ WinException::WinException(AsmPrinter *A) : EHStreamer(A) {
|
|||
// platforms use an imagerel32 relocation to refer to symbols.
|
||||
useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64);
|
||||
isAArch64 = Asm->TM.getTargetTriple().isAArch64();
|
||||
isThumb = Asm->TM.getTargetTriple().isThumb();
|
||||
}
|
||||
|
||||
WinException::~WinException() {}
|
||||
|
@ -330,10 +331,12 @@ const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
|
|||
}
|
||||
|
||||
const MCExpr *WinException::getLabel(const MCSymbol *Label) {
|
||||
if (isAArch64)
|
||||
return MCSymbolRefExpr::create(Label, MCSymbolRefExpr::VK_COFF_IMGREL32,
|
||||
Asm->OutContext);
|
||||
return MCBinaryExpr::createAdd(create32bitRef(Label),
|
||||
return MCSymbolRefExpr::create(Label, MCSymbolRefExpr::VK_COFF_IMGREL32,
|
||||
Asm->OutContext);
|
||||
}
|
||||
|
||||
const MCExpr *WinException::getLabelPlusOne(const MCSymbol *Label) {
|
||||
return MCBinaryExpr::createAdd(getLabel(Label),
|
||||
MCConstantExpr::create(1, Asm->OutContext),
|
||||
Asm->OutContext);
|
||||
}
|
||||
|
@ -561,8 +564,8 @@ InvokeStateChangeIterator &InvokeStateChangeIterator::scan() {
|
|||
/// struct Table {
|
||||
/// int NumEntries;
|
||||
/// struct Entry {
|
||||
/// imagerel32 LabelStart;
|
||||
/// imagerel32 LabelEnd;
|
||||
/// imagerel32 LabelStart; // Inclusive
|
||||
/// imagerel32 LabelEnd; // Exclusive
|
||||
/// imagerel32 FilterOrFinally; // One means catch-all.
|
||||
/// imagerel32 LabelLPad; // Zero means __finally.
|
||||
/// } Entries[NumEntries];
|
||||
|
@ -664,7 +667,7 @@ void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo,
|
|||
AddComment("LabelStart");
|
||||
OS.emitValue(getLabel(BeginLabel), 4);
|
||||
AddComment("LabelEnd");
|
||||
OS.emitValue(getLabel(EndLabel), 4);
|
||||
OS.emitValue(getLabelPlusOne(EndLabel), 4);
|
||||
AddComment(UME.IsFinally ? "FinallyFunclet" : UME.Filter ? "FilterFunction"
|
||||
: "CatchAll");
|
||||
OS.emitValue(FilterOrFinally, 4);
|
||||
|
@ -949,8 +952,15 @@ void WinException::computeIP2StateTable(
|
|||
if (!ChangeLabel)
|
||||
ChangeLabel = StateChange.PreviousEndLabel;
|
||||
// Emit an entry indicating that PCs after 'Label' have this EH state.
|
||||
// NOTE: On ARM architectures, the StateFromIp automatically takes into
|
||||
// account that the return address is after the call instruction (whose EH
|
||||
// state we should be using), but on other platforms we need to +1 to the
|
||||
// label so that we are using the correct EH state.
|
||||
const MCExpr *LabelExpression = (isAArch64 || isThumb)
|
||||
? getLabel(ChangeLabel)
|
||||
: getLabelPlusOne(ChangeLabel);
|
||||
IPToStateTable.push_back(
|
||||
std::make_pair(getLabel(ChangeLabel), StateChange.NewState));
|
||||
std::make_pair(LabelExpression, StateChange.NewState));
|
||||
// FIXME: assert that NewState is between CatchLow and CatchHigh.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,9 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {
|
|||
/// True if we are generating exception handling on Windows for ARM64.
|
||||
bool isAArch64 = false;
|
||||
|
||||
/// True if we are generating exception handling on Windows for ARM (Thumb).
|
||||
bool isThumb = false;
|
||||
|
||||
/// Pointer to the current funclet entry BB.
|
||||
const MachineBasicBlock *CurrentFuncletEntry = nullptr;
|
||||
|
||||
|
@ -77,6 +80,7 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {
|
|||
const MCExpr *create32bitRef(const MCSymbol *Value);
|
||||
const MCExpr *create32bitRef(const GlobalValue *GV);
|
||||
const MCExpr *getLabel(const MCSymbol *Label);
|
||||
const MCExpr *getLabelPlusOne(const MCSymbol *Label);
|
||||
const MCExpr *getOffset(const MCSymbol *OffsetOf, const MCSymbol *OffsetFrom);
|
||||
const MCExpr *getOffsetPlusOne(const MCSymbol *OffsetOf,
|
||||
const MCSymbol *OffsetFrom);
|
||||
|
|
|
@ -61,19 +61,19 @@ catch.body.2:
|
|||
|
||||
; SEH-LABEL: test:
|
||||
; SEH-LABEL: .Llsda_begin0:
|
||||
; SEH-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; SEH-NEXT: .long .Ltmp0@IMGREL
|
||||
; SEH-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; SEH-NEXT: .long dummy_filter@IMGREL
|
||||
; SEH-NEXT: .long .LBB0_3@IMGREL
|
||||
; SEH-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; SEH-NEXT: .long .Ltmp0@IMGREL
|
||||
; SEH-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; SEH-NEXT: .long dummy_filter@IMGREL
|
||||
; SEH-NEXT: .long .LBB0_5@IMGREL
|
||||
; SEH-NEXT: .long .Ltmp2@IMGREL+1
|
||||
; SEH-NEXT: .long .Ltmp2@IMGREL
|
||||
; SEH-NEXT: .long .Ltmp3@IMGREL+1
|
||||
; SEH-NEXT: .long "?dtor$2@?0?test@4HA"@IMGREL
|
||||
; SEH-NEXT: .long 0
|
||||
; SEH-NEXT: .long .Ltmp2@IMGREL+1
|
||||
; SEH-NEXT: .long .Ltmp2@IMGREL
|
||||
; SEH-NEXT: .long .Ltmp3@IMGREL+1
|
||||
; SEH-NEXT: .long dummy_filter@IMGREL
|
||||
; SEH-NEXT: .long .LBB0_5@IMGREL
|
||||
|
|
|
@ -47,7 +47,7 @@ return: ; preds = %catch, %entry
|
|||
; CHECK-NEXT: .set .Lfoo$parent_frame_offset, 32
|
||||
; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
|
||||
; CHECK-NEXT: .Llsda_begin0:
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; CHECK-NEXT: .long 1
|
||||
; CHECK-NEXT: .long .LBB0_[[catch]]@IMGREL
|
||||
|
|
|
@ -120,23 +120,23 @@ __except.ret: ; preds = %catch.dispatch.7
|
|||
; CHECK-NEXT: .set .Lmain$parent_frame_offset, 32
|
||||
; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
|
||||
; CHECK-NEXT: .Llsda_begin0:
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; CHECK-NEXT: .long 1
|
||||
; CHECK-NEXT: .long .LBB1_[[except1bb]]@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
|
||||
; CHECK-NEXT: .long .LBB1_[[except2bb]]@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp2@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp2@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp3@IMGREL+1
|
||||
; CHECK-NEXT: .long "?dtor$[[finbb:[0-9]+]]@?0?main@4HA"@IMGREL
|
||||
; CHECK-NEXT: .long 0
|
||||
; CHECK-NEXT: .long .Ltmp2@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp2@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp3@IMGREL+1
|
||||
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
|
||||
; CHECK-NEXT: .long .LBB1_3@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp6@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp6@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp7@IMGREL+1
|
||||
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
|
||||
; CHECK-NEXT: .long .LBB1_3@IMGREL
|
||||
|
|
|
@ -82,15 +82,15 @@ __try.cont: ; preds = %__except, %invoke.c
|
|||
; CHECK-NEXT: .Luse_both$parent_frame_offset
|
||||
; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
|
||||
; CHECK-NEXT: .Llsda_begin0:
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; CHECK-NEXT: .long "?dtor$2@?0?use_both@4HA"@IMGREL
|
||||
; CHECK-NEXT: .long 0
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; CHECK-NEXT: .long "?filt$0@0@use_both@@"@IMGREL
|
||||
; CHECK-NEXT: .long .LBB0_{{[0-9]+}}@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp4@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp4@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp5@IMGREL+1
|
||||
; CHECK-NEXT: .long "?filt$0@0@use_both@@"@IMGREL
|
||||
; CHECK-NEXT: .long .LBB0_{{[0-9]+}}@IMGREL
|
||||
|
|
|
@ -29,7 +29,7 @@ lpad: ; preds = %entry
|
|||
; X64-NEXT: .set .Lmain$parent_frame_offset, 32
|
||||
; X64-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16 # Number of call sites
|
||||
; X64-NEXT: .Llsda_begin0:
|
||||
; X64-NEXT: .long .Ltmp0@IMGREL+1 # LabelStart
|
||||
; X64-NEXT: .long .Ltmp0@IMGREL # LabelStart
|
||||
; X64-NEXT: .long .Ltmp1@IMGREL+1 # LabelEnd
|
||||
; X64-NEXT: .long "?dtor$2@?0?main@4HA"@IMGREL # FinallyFunclet
|
||||
; X64-NEXT: .long 0 # Null
|
||||
|
|
|
@ -81,11 +81,11 @@ __try.cont:
|
|||
; CHECK-NEXT: .Lsafe_div$parent_frame_offset
|
||||
; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
|
||||
; CHECK-NEXT: .Llsda_begin0:
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; CHECK-NEXT: .long safe_div_filt0@IMGREL
|
||||
; CHECK-NEXT: .long [[handler0]]@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; CHECK-NEXT: .long .Ltmp0@IMGREL
|
||||
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; CHECK-NEXT: .long safe_div_filt1@IMGREL
|
||||
; CHECK-NEXT: .long [[handler1]]@IMGREL
|
||||
|
|
Loading…
Reference in New Issue