[llvm-commits] [PATCH] Teach llvm-objdump to dump Win64 exception tables
Kai
kai at redstar.de
Mon Nov 12 13:42:33 PST 2012
Ping!
I updates the patch with the following:
- removed trailing space
- added missing CMake entry
Regards
Kai
On 02.11.2012 18:56, Kai wrote:
> Hi!
>
> I re-used a test case which generates unwind info with llvm-mc. During
> construction of the test I noticed some small problems which I fixed. I
> also silenced some GCC warnings and added decoding of the flags field.
> The attached patches are updated accordingly.
>
> @Michael
> I reused the content of the MC/Object/seh.s test. While studying the
> generated tables I noticed that there is a UOP_PushMachFrame generated
> as last unwind code in the table. Is this correct? I can't related this
> unwind code to the .seh_* operations in the source. The entry order
> seems also wrong. From the first function:
>
> Unwind Codes:
> 0x00: UOP_SetFPReg
> 0x0f: UOP_PushNonVol RBX
> 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
> 0x09: UOP_SaveNonVol RSI [0x0010]
> 0x04: UOP_AllocSmall 24
> 0x00: UOP_PushMachFrame w/o error code
>
> From the source I would expect the following:
>
> Unwind Codes:
> 0x0f: UOP_PushNonVol RBX
> 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
> 0x09: UOP_SaveNonVol RSI [0x0010]
> 0x04: UOP_AllocSmall 24
> 0x00: UOP_SetFPReg
>
> Regards
> Kai
>
> On 02.11.2012 15:31, João Matos wrote:
>> On Fri, Nov 2, 2012 at 1:33 PM, Kai
>> <kai at redstar.de
>> <mailto:kai at redstar.de>> wrote:
>>
>> I am going to place a test into folder test/Other (hopefully it fits
>> there) but I still have trouble to create some good input. Do you
>> have a suggestion how to do it?
>>
>>
>> We discussed this once on IRC and IIRC the usage of the COFF YAML tools
>> was suggested so there would be no need to commit binary COFF files.
>>
>> --
>> João Matos
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
diff --git a/test/Other/llvm-objdump-unwind.s b/test/Other/llvm-objdump-unwind.s
new file mode 100644
index 0000000..1e4c742
--- /dev/null
+++ b/test/Other/llvm-objdump-unwind.s
@@ -0,0 +1,106 @@
+// This test checks that the unwind data is dumped by llvm-objdump.
+// RUN: llvm-mc -triple x86_64-pc-win32 -filetype=obj %s | llvm-objdump -u - | FileCheck %s
+
+// CHECK: Unwind info:
+// CHECK: Function Table:
+// CHECK-NEXT: Start Address: .text
+// CHECK-NEXT: End Address: .text + 0x001b
+// CHECK-NEXT: Unwind Info Address: .xdata
+// CHECK-NEXT: Version: 1
+// CHECK-NEXT: Flags: 1 UNW_ExceptionHandler
+// CHECK-NEXT: Size of prolog: 18
+// CHECK-NEXT: Number of Codes: 8
+// CHECK-NEXT: Frame register: RBX
+// CHECK-NEXT: Frame offset: 0
+// CHECK-NEXT: Unwind Codes:
+// CHECK-NEXT: 0x00: UOP_SetFPReg
+// CHECK-NEXT: 0x0f: UOP_PushNonVol RBX
+// CHECK-NEXT: 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
+// CHECK-NEXT: 0x09: UOP_SaveNonVol RSI [0x0010]
+// 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: Unwind Info Address: .xdata + 0x001c
+// CHECK-NEXT: Version: 1
+// CHECK-NEXT: Flags: 4 UNW_ChainInfo
+// CHECK-NEXT: Size of prolog: 0
+// 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: Unwind Info Address: .xdata + 0x002c
+// CHECK-NEXT: Version: 1
+// CHECK-NEXT: Flags: 0
+// CHECK-NEXT: Size of prolog: 0
+// 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: Unwind Info Address: .xdata + 0x0034
+// CHECK-NEXT: Version: 1
+// CHECK-NEXT: Flags: 0
+// CHECK-NEXT: Size of prolog: 14
+// CHECK-NEXT: Number of Codes: 6
+// CHECK-NEXT: No frame pointer used
+// CHECK-NEXT: Unwind Codes:
+// CHECK-NEXT: 0x0e: UOP_AllocLarge 8454128
+// CHECK-NEXT: 0x07: UOP_AllocLarge 8190
+// CHECK-NEXT: 0x00: UOP_PushMachFrame w/o error code
+
+ .text
+ .globl func
+ .def func; .scl 2; .type 32; .endef
+ .seh_proc func
+func:
+ .seh_pushframe @code
+ subq $24, %rsp
+ .seh_stackalloc 24
+ movq %rsi, 16(%rsp)
+ .seh_savereg %rsi, 16
+ movups %xmm8, (%rsp)
+ .seh_savexmm %xmm8, 0
+ pushq %rbx
+ .seh_pushreg 3
+ mov %rsp, %rbx
+ .seh_setframe 3, 0
+ .seh_endprologue
+ .seh_handler __C_specific_handler, @except
+ .seh_handlerdata
+ .long 0
+ .text
+ .seh_startchained
+ .seh_endprologue
+ .seh_endchained
+ lea (%rbx), %rsp
+ pop %rbx
+ addq $24, %rsp
+ ret
+ .seh_endproc
+
+// Test emission of small functions.
+ .globl smallFunc
+ .def smallFunc; .scl 2; .type 32; .endef
+ .seh_proc smallFunc
+smallFunc:
+ ret
+ .seh_endproc
+
+// Function with big stack allocation.
+ .globl smallFunc
+ .def allocFunc; .scl 2; .type 32; .endef
+ .seh_proc smallFunc
+allocFunc:
+ .seh_pushframe @code
+ subq $65520, %rsp
+ .seh_stackalloc 65520
+ sub $8454128, %rsp
+ .seh_stackalloc 8454128
+ .seh_endprologue
+ add $8454128, %rsp
+ addq $65520, %rsp
+ ret
+ .seh_endproc
diff --git a/tools/llvm-objdump/CMakeLists.txt b/tools/llvm-objdump/CMakeLists.txt
index f3b2e1f..5001435 100644
--- a/tools/llvm-objdump/CMakeLists.txt
+++ b/tools/llvm-objdump/CMakeLists.txt
@@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_tool(llvm-objdump
llvm-objdump.cpp
+ COFFDump.cpp
MachODump.cpp
MCFunction.cpp
)
diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp
new file mode 100644
index 0000000..6237355
--- /dev/null
+++ b/tools/llvm-objdump/COFFDump.cpp
@@ -0,0 +1,310 @@
+//===-- llvm-objdump.cpp - Object file dumping utility for llvm -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the COFF-specific dumper for llvm-objdump.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-objdump.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+#include "llvm/Support/Win64EH.h"
+#include <algorithm>
+#include <cstring>
+using namespace llvm;
+using namespace object;
+
+namespace {
+ using namespace llvm::Win64EH;
+
+ llvm::raw_ostream &writeHexNumber(llvm::raw_ostream &Out,
+ unsigned long long N) {
+ if (N >= 10)
+ Out << "0x";
+ Out.write_hex(N);
+ return Out;
+ }
+
+ StringRef GetCOFFUnwindCodeTypeName(uint8_t Code) {
+ switch(Code) {
+ default: llvm_unreachable("Invalid unwind code");
+ case UOP_PushNonVol: return "UOP_PushNonVol";
+ case UOP_AllocLarge: return "UOP_AllocLarge";
+ case UOP_AllocSmall: return "UOP_AllocSmall";
+ case UOP_SetFPReg: return "UOP_SetFPReg";
+ case UOP_SaveNonVol: return "UOP_SaveNonVol";
+ case UOP_SaveNonVolBig: return "UOP_SaveNonVolBig";
+ case UOP_SaveXMM128: return "UOP_SaveXMM128";
+ case UOP_SaveXMM128Big: return "UOP_SaveXMM128Big";
+ case UOP_PushMachFrame: return "UOP_PushMachFrame";
+ }
+ }
+
+ StringRef GetCOFFUnwindRegisterName(uint8_t Reg) {
+ switch(Reg) {
+ default: llvm_unreachable("Invalid register");
+ case 0: return "RAX";
+ case 1: return "RCX";
+ case 2: return "RDX";
+ case 3: return "RBX";
+ case 4: return "RSP";
+ case 5: return "RBP";
+ case 6: return "RSI";
+ case 7: return "RDI";
+ case 8: return "R8";
+ case 9: return "R9";
+ case 10: return "R10";
+ case 11: return "R11";
+ case 12: return "R12";
+ case 13: return "R13";
+ case 14: return "R14";
+ case 15: return "R15";
+ }
+ }
+
+ void PrintCOFFUnwindCode(const UnwindCode* UnwindCodes, unsigned numCodes) {
+ for (unsigned i = 0; i < numCodes; i++) {
+ const UnwindCode& UC = UnwindCodes[i];
+ outs() << format(" 0x%02x: ", unsigned(UC.u.codeOffset))
+ << GetCOFFUnwindCodeTypeName(UC.u.unwindOp);
+ switch (UC.u.unwindOp) {
+ case UOP_PushNonVol:
+ outs() << " " << GetCOFFUnwindRegisterName(UC.u.opInfo);
+ break;
+ case UOP_AllocLarge: {
+ uint32_t size;
+ if (UC.u.opInfo == 0) {
+ size = UnwindCodes[++i].frameOffset;
+ }
+ else {
+ size = UnwindCodes[i+1].frameOffset
+ + (((uint32_t) UnwindCodes[i+2].frameOffset) << 16);
+ i += 2;
+ }
+ outs() << " " << size;
+ break;
+ }
+ case UOP_AllocSmall:
+ outs() << " " << ((UC.u.opInfo+1) * 8);
+ break;
+ case UOP_SetFPReg:
+ outs() << " ";
+ break;
+ case UOP_SaveNonVol:
+ outs() << " " << GetCOFFUnwindRegisterName(UC.u.opInfo)
+ << format(" [0x%04x]", 8 * UnwindCodes[++i].frameOffset);
+ break;
+ case UOP_SaveNonVolBig: {
+ uint32_t ofs = UnwindCodes[i+1].frameOffset
+ + (((uint32_t) UnwindCodes[i+2].frameOffset) << 16);
+ i += 2;
+ outs() << " " << GetCOFFUnwindRegisterName(UC.u.opInfo)
+ << format(" [0x%08x]", ofs);
+ break;
+ }
+ case UOP_SaveXMM128:
+ outs() << " XMM" << static_cast<uint32_t>(UC.u.opInfo)
+ << format(" [0x%04x]", 16 * UnwindCodes[++i].frameOffset);
+ break;
+ case UOP_SaveXMM128Big: {
+ uint32_t ofs = UnwindCodes[i+1].frameOffset
+ + (((uint32_t) UnwindCodes[i+2].frameOffset) << 16);
+ i += 2;
+ outs() << " XMM" << UC.u.opInfo << format(" [0x%08x]", ofs);
+ break;
+ }
+ case UOP_PushMachFrame:
+ outs() << " " << (UC.u.opInfo ? "w/o" : "w") << " error code";
+ break;
+ }
+ outs() << "\n";
+ }
+ }
+
+ error_code ResolveCOFFRelocation(const COFFObjectFile* o,
+ const SymbolRef& sym,
+ const coff_section*& ResolvedSection,
+ uint64_t& ResolvedAddr) {
+ error_code ec;
+ if ((ec = sym.getAddress(ResolvedAddr))) return ec;
+ section_iterator iter(o->begin_sections());
+ if ((ec = sym.getSection(iter))) return ec;
+ ResolvedSection = o->getCOFFSection(iter);
+ return object_error::success;
+ }
+
+ error_code GetCOFFUnwindInfo(const COFFObjectFile* o,
+ const std::vector<RelocationRef> Rels,
+ uint64_t offset, ArrayRef<uint8_t>& Contents,
+ uint64_t& addr) {
+ for (std::vector<RelocationRef>::const_iterator R = Rels.begin();
+ R != Rels.end(); R++) {
+ error_code ec;
+ uint64_t ofs;
+ if ((ec = R->getOffset(ofs))) return ec;
+ if (ofs == offset) {
+ SymbolRef sym;
+ if ((ec = R->getSymbol(sym))) return ec;
+ const coff_section* section;
+ ResolveCOFFRelocation(o, sym, section, addr);
+ if ((ec = o->getSectionContents(section, Contents))) return ec;
+ break;
+ }
+ }
+ return object_error::success;
+ }
+
+ error_code GetCOFFSymbol(const std::vector<RelocationRef> Rels,
+ uint64_t offset, StringRef& name) {
+ for (std::vector<RelocationRef>::const_iterator R = Rels.begin();
+ R != Rels.end(); R++) {
+ error_code ec;
+ uint64_t ofs;
+ if ((ec = R->getOffset(ofs))) return ec;
+ if (ofs == offset) {
+ SymbolRef sym;
+ if ((ec = R->getSymbol(sym))) return ec;
+ if ((ec = sym.getName(name))) return ec;
+ break;
+ }
+ }
+ return object_error::success;
+ }
+
+ void PrintCOFFSymbolAddress(llvm::raw_ostream &Out,
+ const std::vector<RelocationRef> Rels,
+ uint64_t offset, uint32_t disp) {
+ StringRef sym;
+ GetCOFFSymbol(Rels, offset, sym);
+ Out << sym;
+ if (disp > 0)
+ Out << format(" + 0x%04x", disp);
+ }
+}
+
+void llvm::PrintCOFFUnwindInfo(const COFFObjectFile* o) {
+ const coff_file_header *header;
+ if (error(o->getHeader(header))) return;
+
+ if (header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
+ errs() << "Unsupported image machine type "
+ "(currently only AMD64 is supported).\n";
+ return;
+ }
+
+ const coff_section* pdata = 0;
+
+ error_code ec;
+ for (section_iterator si = o->begin_sections(),
+ se = o->end_sections();
+ si != se; si.increment(ec)) {
+ if (error(ec)) return;
+
+ StringRef Name;
+ if (error(si->getName(Name))) continue;
+
+ if (Name.compare(".pdata") == 0) {
+ pdata = o->getCOFFSection(si);
+ std::vector<RelocationRef> Rels;
+ for (relocation_iterator ri = si->begin_relocations(),
+ re = si->end_relocations();
+ ri != re; ri.increment(ec)) {
+ if (error(ec)) break;
+ Rels.push_back(*ri);
+ }
+
+ // Sort relocations by address.
+ std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
+
+ ArrayRef<uint8_t> Contents;
+ if (error(o->getSectionContents(pdata, Contents))) continue;
+ if (Contents.empty()) continue;
+
+ unsigned i = 0;
+ while ((Contents.size() - i) >= sizeof(RuntimeFunction)) {
+ const RuntimeFunction* RF =
+ reinterpret_cast<const RuntimeFunction*>(Contents.data() + i);
+
+ outs() << "Function Table:\n";
+
+ outs() << " Start Address: ";
+ PrintCOFFSymbolAddress(outs(), Rels,
+ i + offsetof(RuntimeFunction, startAddress),
+ RF->startAddress);
+ outs() << "\n";
+
+ outs() << " End Address: ";
+ PrintCOFFSymbolAddress(outs(), Rels,
+ i + offsetof(RuntimeFunction, endAddress),
+ RF->endAddress);
+ outs() << "\n";
+
+ outs() << " Unwind Info Address: ";
+ PrintCOFFSymbolAddress(outs(), Rels,
+ i + offsetof(RuntimeFunction, unwindInfoOffset),
+ RF->unwindInfoOffset);
+ outs() << "\n";
+
+ ArrayRef<uint8_t> XContents;
+ uint64_t UnwindInfoOffset = 0;
+ if (error(GetCOFFUnwindInfo(o, Rels,
+ i + offsetof(RuntimeFunction, unwindInfoOffset),
+ XContents, UnwindInfoOffset))) continue;
+ if (XContents.empty()) continue;
+
+ UnwindInfoOffset += RF->unwindInfoOffset;
+ if (UnwindInfoOffset > XContents.size()) continue;
+
+ const Win64EH::UnwindInfo* UI = reinterpret_cast<const Win64EH::UnwindInfo*>
+ (XContents.data() + UnwindInfoOffset);
+
+ outs() << " Version: " << (int) UI->version << "\n";
+ outs() << " Flags: " << (int) UI->flags;
+ if (UI->flags) {
+ if (UI->flags & UNW_ExceptionHandler) outs() << " UNW_ExceptionHandler";
+ if (UI->flags & UNW_TerminateHandler) outs() << " UNW_TerminateHandler";
+ if (UI->flags & UNW_ChainInfo) outs() << " UNW_ChainInfo";
+ }
+ outs() << "\n";
+ outs() << " Size of prolog: " << (int) UI->prologSize << "\n";
+ outs() << " Number of Codes: " << (int) UI->numCodes << "\n";
+ // Maybe this should move to output of UOP_SetFPReg?
+ if (UI->frameRegister) {
+ outs() << " Frame register: "
+ << GetCOFFUnwindRegisterName(UI->frameRegister) << "\n";
+ outs() << " Frame offset: " << 16 * (int) UI->frameOffset << "\n";
+ }
+ else {
+ outs() << " No frame pointer used\n";
+ }
+ if (UI->flags & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
+ // FIXME: Output exception handler data
+ }
+ else if (UI->flags & UNW_ChainInfo) {
+ // FIXME: Output chained unwind info
+ }
+
+ if (UI->numCodes)
+ outs() << " Unwind Codes:\n";
+
+ PrintCOFFUnwindCode(&UI->unwindCodes[0], UI->numCodes);
+
+ outs() << "\n\n";
+ outs().flush();
+
+ i += sizeof(RuntimeFunction);
+ }
+ continue;
+ }
+ }
+}
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index 13ea4e3..1028b48 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -100,9 +100,16 @@ MAttrs("mattr",
cl::desc("Target specific attributes"),
cl::value_desc("a1,+a2,-a3,..."));
+static cl::opt<bool>
+UnwindInfo("unwind-info", cl::desc("Display unwind information"));
+
+static cl::alias
+UnwindInfoShort("u", cl::desc("Alias for --unwind-info"),
+ cl::aliasopt(::UnwindInfo));
+
static StringRef ToolName;
-static bool error(error_code ec) {
+bool llvm::error(error_code ec) {
if (!ec) return false;
outs() << ToolName << ": error reading file: " << ec.message() << ".\n";
@@ -161,7 +168,7 @@ void llvm::DumpBytes(StringRef bytes) {
outs() << output;
}
-static bool RelocAddressLess(RelocationRef a, RelocationRef b) {
+bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
uint64_t a_addr, b_addr;
if (error(a.getAddress(a_addr))) return false;
if (error(b.getAddress(b_addr))) return false;
@@ -566,6 +573,19 @@ static void PrintSymbolTable(const ObjectFile *o) {
}
}
+static void PrintUnwindInfo(const ObjectFile *o) {
+ outs() << "Unwind info:\n\n";
+
+ if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
+ PrintCOFFUnwindInfo(coff);
+ } else {
+ // TODO: Extract DWARF dump tool to objdump.
+ errs() << "This operation is only currently supported "
+ "for COFF object files.\n";
+ return;
+ }
+}
+
static void DumpObject(const ObjectFile *o) {
outs() << '\n';
outs() << o->getFileName()
@@ -581,6 +601,8 @@ static void DumpObject(const ObjectFile *o) {
PrintSectionContents(o);
if (SymbolTable)
PrintSymbolTable(o);
+ if (::UnwindInfo)
+ PrintUnwindInfo(o);
}
/// @brief Dump each object file in \a a;
@@ -659,7 +681,8 @@ int main(int argc, char **argv) {
&& !Relocations
&& !SectionHeaders
&& !SectionContents
- && !SymbolTable) {
+ && !SymbolTable
+ && !::UnwindInfo) {
cl::PrintHelpMessage();
return 2;
}
diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h
index aa71b77..bf3d422 100644
--- a/tools/llvm-objdump/llvm-objdump.h
+++ b/tools/llvm-objdump/llvm-objdump.h
@@ -17,12 +17,21 @@
namespace llvm {
+namespace object {
+ class COFFObjectFile;
+ class RelocationRef;
+}
+class error_code;
+
extern cl::opt<std::string> TripleName;
extern cl::opt<std::string> ArchName;
// Various helper functions.
+bool error(error_code ec);
+bool RelocAddressLess(object::RelocationRef a, object::RelocationRef b);
void DumpBytes(StringRef bytes);
void DisassembleInputMachO(StringRef Filename);
+void PrintCOFFUnwindInfo(const object::COFFObjectFile* o);
class StringRefMemoryObject : public MemoryObject {
virtual void anchor();
-------------- next part --------------
diff --git a/include/llvm/Support/Win64EH.h b/include/llvm/Support/Win64EH.h
index 8d74e10..fb8aeae 100644
--- a/include/llvm/Support/Win64EH.h
+++ b/include/llvm/Support/Win64EH.h
@@ -60,9 +60,9 @@ enum {
/// RuntimeFunction - An entry in the table of functions with unwind info.
struct RuntimeFunction {
- uint64_t startAddress;
- uint64_t endAddress;
- uint64_t unwindInfoOffset;
+ uint32_t startAddress;
+ uint32_t endAddress;
+ uint32_t unwindInfoOffset;
};
/// UnwindInfo - An entry in the exception table.
@@ -78,17 +78,17 @@ struct UnwindInfo {
void *getLanguageSpecificData() {
return reinterpret_cast<void *>(&unwindCodes[(numCodes+1) & ~1]);
}
- uint64_t getLanguageSpecificHandlerOffset() {
- return *reinterpret_cast<uint64_t *>(getLanguageSpecificData());
+ uint32_t getLanguageSpecificHandlerOffset() {
+ return *reinterpret_cast<uint32_t *>(getLanguageSpecificData());
}
- void setLanguageSpecificHandlerOffset(uint64_t offset) {
+ void setLanguageSpecificHandlerOffset(uint32_t offset) {
*reinterpret_cast<uint64_t *>(getLanguageSpecificData()) = offset;
}
RuntimeFunction *getChainedFunctionEntry() {
return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData());
}
void *getExceptionData() {
- return reinterpret_cast<void *>(reinterpret_cast<uint64_t *>(
+ return reinterpret_cast<void *>(reinterpret_cast<uint32_t *>(
getLanguageSpecificData())+1);
}
};
More information about the llvm-commits
mailing list