From 7185bdd88302a67618b2edf51c499d647e5ff492 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Sun, 15 Sep 2013 17:46:46 +0000 Subject: [PATCH] Generate IMAGE_REL_AMD64_ADDR32NB relocations for SEH data structures. The Win64 EH data structures must be of type IMAGE_REL_AMD64_ADDR32NB instead of IMAGE_REL_AMD64_ADDR32. This is easiely achieved by adding the VK_COFF_IMGREL32 modifier to the symbol reference. Change also references to start and end of the SEH range of a function as offsets to start of the function. Reviewed by Jim Grosbach, Charles Davis and Nico Rieck. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190766 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCWin64EH.cpp | 26 +++++++++++++++++---- test/MC/COFF/seh.s | 23 +++++++++++++++++- test/tools/llvm-objdump/win64-unwind-data.s | 20 ++++++++-------- 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp index 8db1fa2a93c..c3d568b454c 100644 --- a/lib/MC/MCWin64EH.cpp +++ b/lib/MC/MCWin64EH.cpp @@ -128,14 +128,29 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin, } } +static void EmitSymbolRefWithOfs(MCStreamer &streamer, + const MCSymbol *Base, + const MCSymbol *Other) { + MCContext &Context = streamer.getContext(); + const MCSymbolRefExpr *BaseRef = MCSymbolRefExpr::Create(Base, Context); + const MCSymbolRefExpr *OtherRef = MCSymbolRefExpr::Create(Other, Context); + const MCExpr *Ofs = MCBinaryExpr::CreateSub(OtherRef, BaseRef, Context); + const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::Create(Base, + MCSymbolRefExpr::VK_COFF_IMGREL32, + Context); + streamer.EmitValue(MCBinaryExpr::CreateAdd(BaseRefRel, Ofs, Context), 4); +} + static void EmitRuntimeFunction(MCStreamer &streamer, const MCWin64EHUnwindInfo *info) { MCContext &context = streamer.getContext(); streamer.EmitValueToAlignment(4); - streamer.EmitValue(MCSymbolRefExpr::Create(info->Begin, context), 4); - streamer.EmitValue(MCSymbolRefExpr::Create(info->End, context), 4); - streamer.EmitValue(MCSymbolRefExpr::Create(info->Symbol, context), 4); + EmitSymbolRefWithOfs(streamer, info->Function, info->Begin); + EmitSymbolRefWithOfs(streamer, info->Function, info->End); + streamer.EmitValue(MCSymbolRefExpr::Create(info->Symbol, + MCSymbolRefExpr::VK_COFF_IMGREL32, + context), 4); } static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { @@ -188,8 +203,9 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { EmitRuntimeFunction(streamer, info->ChainedParent); else if (flags & ((Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler) << 3)) - streamer.EmitValue(MCSymbolRefExpr::Create(info->ExceptionHandler, context), - 4); + streamer.EmitValue(MCSymbolRefExpr::Create(info->ExceptionHandler, + MCSymbolRefExpr::VK_COFF_IMGREL32, + context), 4); else if (numCodes < 2) { // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not // a chained unwind info, if there is no handler, and if there are fewer diff --git a/test/MC/COFF/seh.s b/test/MC/COFF/seh.s index b1e61a97739..72d42f4b2ea 100644 --- a/test/MC/COFF/seh.s +++ b/test/MC/COFF/seh.s @@ -1,6 +1,6 @@ // This test checks that the SEH directives emit the correct unwind data. -// RUN: llvm-mc -triple x86_64-pc-win32 -filetype=obj %s | llvm-readobj -s -u | FileCheck %s +// RUN: llvm-mc -triple x86_64-pc-win32 -filetype=obj %s | llvm-readobj -s -u -r | FileCheck %s // CHECK: Sections [ // CHECK: Section { @@ -34,6 +34,27 @@ // CHECK-NEXT: } // CHECK-NEXT: ] +// CHECK-NEXT: Relocations [ +// CHECK-NEXT: Section (2) .xdata { +// CHECK-NEXT: 0x14 IMAGE_REL_AMD64_ADDR32NB __C_specific_handler +// CHECK-NEXT: 0x20 IMAGE_REL_AMD64_ADDR32NB func +// CHECK-NEXT: 0x24 IMAGE_REL_AMD64_ADDR32NB func +// CHECK-NEXT: 0x28 IMAGE_REL_AMD64_ADDR32NB .xdata +// CHECK-NEXT: } +// CHECK-NEXT: Section (3) .pdata { +// CHECK-NEXT: 0x0 IMAGE_REL_AMD64_ADDR32NB func +// CHECK-NEXT: 0x4 IMAGE_REL_AMD64_ADDR32NB func +// CHECK-NEXT: 0x8 IMAGE_REL_AMD64_ADDR32NB .xdata +// CHECK-NEXT: 0xC IMAGE_REL_AMD64_ADDR32NB func +// CHECK-NEXT: 0x10 IMAGE_REL_AMD64_ADDR32NB func +// CHECK-NEXT: 0x14 IMAGE_REL_AMD64_ADDR32NB .xdata +// CHECK-NEXT: 0x18 IMAGE_REL_AMD64_ADDR32NB smallFunc +// CHECK-NEXT: 0x1C IMAGE_REL_AMD64_ADDR32NB smallFunc +// CHECK-NEXT: 0x20 IMAGE_REL_AMD64_ADDR32NB .xdata +// CHECK-NEXT: } +// CHECK-NEXT: ] + + // CHECK: UnwindInformation [ // CHECK-NEXT: RuntimeFunction { // CHECK-NEXT: StartAddress: [[CodeSect1:[^ ]+]] [[BeginDisp1:(\+0x[A-F0-9]+)?]] diff --git a/test/tools/llvm-objdump/win64-unwind-data.s b/test/tools/llvm-objdump/win64-unwind-data.s index a172bfca6b3..f8463fb062c 100644 --- a/test/tools/llvm-objdump/win64-unwind-data.s +++ b/test/tools/llvm-objdump/win64-unwind-data.s @@ -3,8 +3,8 @@ // CHECK: Unwind info: // CHECK: Function Table: -// CHECK-NEXT: Start Address: .text -// CHECK-NEXT: End Address: .text + 0x001b +// CHECK-NEXT: Start Address: func +// CHECK-NEXT: End Address: func + 0x001b // CHECK-NEXT: Unwind Info Address: .xdata // CHECK-NEXT: Version: 1 // CHECK-NEXT: Flags: 1 UNW_ExceptionHandler @@ -20,8 +20,8 @@ // CHECK-NEXT: 0x04: UOP_AllocSmall 24 // CHECK-NEXT: 0x00: UOP_PushMachFrame w/o error code // CHECK: Function Table: -// CHECK-NEXT: Start Address: .text + 0x0012 -// CHECK-NEXT: End Address: .text + 0x0012 +// CHECK-NEXT: Start Address: func + 0x0012 +// CHECK-NEXT: End Address: func + 0x0012 // CHECK-NEXT: Unwind Info Address: .xdata + 0x001c // CHECK-NEXT: Version: 1 // CHECK-NEXT: Flags: 4 UNW_ChainInfo @@ -29,8 +29,8 @@ // CHECK-NEXT: Number of Codes: 0 // CHECK-NEXT: No frame pointer used // CHECK: Function Table: -// CHECK-NEXT: Start Address: .text + 0x001b -// CHECK-NEXT: End Address: .text + 0x001c +// CHECK-NEXT: Start Address: smallFunc +// CHECK-NEXT: End Address: smallFunc + 0x0001 // CHECK-NEXT: Unwind Info Address: .xdata + 0x002c // CHECK-NEXT: Version: 1 // CHECK-NEXT: Flags: 0 @@ -38,8 +38,8 @@ // CHECK-NEXT: Number of Codes: 0 // CHECK-NEXT: No frame pointer used // CHECK: Function Table: -// CHECK-NEXT: Start Address: .text + 0x001c -// CHECK-NEXT: End Address: .text + 0x0039 +// CHECK-NEXT: Start Address: allocFunc +// CHECK-NEXT: End Address: allocFunc + 0x001d // CHECK-NEXT: Unwind Info Address: .xdata + 0x0034 // CHECK-NEXT: Version: 1 // CHECK-NEXT: Flags: 0 @@ -90,9 +90,9 @@ smallFunc: .seh_endproc // Function with big stack allocation. - .globl smallFunc + .globl allocFunc .def allocFunc; .scl 2; .type 32; .endef - .seh_proc smallFunc + .seh_proc allocFunc allocFunc: .seh_pushframe @code subq $65520, %rsp -- 2.34.1