Skip to content

Commit

Permalink
[MC] [Win64EH] Fill in FuncletOrFuncEnd if missing
Browse files Browse the repository at this point in the history
This can happen e.g. for code that declare .seh_proc/.seh_endproc
in assembly, or for code that use .seh_handlerdata (which triggers
the unwind info to be emitted before the end of the function).

The TextSection field must be made non-const to be able to use it
with Streamer.SwitchSection().

Differential Revision: https://reviews.llvm.org/D86528
  • Loading branch information
mstorsjo committed Aug 29, 2020
1 parent 71ac910 commit 20f7773
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 4 deletions.
2 changes: 1 addition & 1 deletion llvm/include/llvm/MC/MCWinEH.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct FrameInfo {
const MCSymbol *Function = nullptr;
const MCSymbol *PrologEnd = nullptr;
const MCSymbol *Symbol = nullptr;
const MCSection *TextSection = nullptr;
MCSection *TextSection = nullptr;

bool HandlesUnwind = false;
bool HandlesExceptions = false;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/MC/MCStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,8 @@ void MCStreamer::EmitWinCFIEndProc(SMLoc Loc) {

MCSymbol *Label = emitCFILabel();
CurFrame->End = Label;
if (!CurFrame->FuncletOrFuncEnd)
CurFrame->FuncletOrFuncEnd = CurFrame->End;
}

void MCStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
Expand Down
14 changes: 11 additions & 3 deletions llvm/lib/MC/MCWin64EH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,7 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {

int64_t RawFuncLength;
if (!info->FuncletOrFuncEnd) {
// FIXME: This is very wrong; we emit SEH data which covers zero bytes
// of code. But otherwise test/MC/AArch64/seh.s crashes.
RawFuncLength = 0;
report_fatal_error("FuncletOrFuncEnd not set");
} else {
// FIXME: GetAbsDifference tries to compute the length of the function
// immediately, before the whole file is emitted, but in general
Expand Down Expand Up @@ -702,6 +700,16 @@ void llvm::Win64EH::ARM64UnwindEmitter::Emit(MCStreamer &Streamer) const {

void llvm::Win64EH::ARM64UnwindEmitter::EmitUnwindInfo(
MCStreamer &Streamer, WinEH::FrameInfo *info) const {
// Called if there's an .seh_handlerdata directive before the end of the
// function. This forces writing the xdata record already here - and
// in this case, the function isn't actually ended already, but the xdata
// record needs to know the function length. In these cases, if the funclet
// end hasn't been marked yet, the xdata function length won't cover the
// whole function, only up to this point.
if (!info->FuncletOrFuncEnd) {
Streamer.SwitchSection(info->TextSection);
info->FuncletOrFuncEnd = Streamer.emitCFILabel();
}
// Switch sections (the static function above is meant to be called from
// here and from Emit().
MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
Expand Down
6 changes: 6 additions & 0 deletions llvm/test/MC/AArch64/seh.s
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]

// CHECK-NEXT: UnwindInformation [
// CHECK-NEXT: RuntimeFunction {
// CHECK-NEXT: Function: func
// CHECK-NEXT: ExceptionRecord: .xdata
// CHECK-NEXT: ExceptionData {
// CHECK-NEXT: FunctionLength: 8

.text
.globl func
Expand Down

0 comments on commit 20f7773

Please sign in to comment.