[llvm-bugs] [Bug 37178] New: JIT Compiler generates incorrect SEH x64 RVA addresses in .data section

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Apr 19 06:42:52 PDT 2018


https://bugs.llvm.org/show_bug.cgi?id=37178

            Bug ID: 37178
           Summary: JIT Compiler generates incorrect SEH x64 RVA addresses
                    in .data section
           Product: new-bugs
           Version: 5.0
          Hardware: PC
                OS: Windows 2000
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: atlaste at yahoo.com
                CC: llvm-bugs at lists.llvm.org

Hi,

This bug is about x64 SEH C++ (CxxFrameHandler3) exceptions using a JIT. We
have these working at the moment, so I'll first discuss the issue and then a
workaround.

Somewhere during the process of generating the LLVM code for catching a SEH
exception, you need to register the type information of the exception you're
going to use. The exception handling itself is done using catchpads, etc.

Relevant here is the type information of the object that you're going to catch,
which will eventually end up in the .data section in the memory manager. The
relevant code can be found below in appendix #1.

During compilation, a function table is generated with the exception handling
data. For each handler in the catch pad, a single handler type entry is
generated with some information. In appendix #2 you'll find a definition of the
structure, which is defined in LLVM using a call to CreateCatchPad.

The issue has to do with the value of pType in this structure. What basically
happens is that the pType will be an RVA, pointing to a .data section. However,
the .data section is emitted first in the JIT, so the RVA address will be 0.
Unfortunately, the value '0' has a special meaning for CxxFrameHandler3, which
corresponds to 'catch everything'. In other words: exception filtering won't
work in the JIT if an RVA of 0 is present -- and the default is to generate RVA
0 for the first typeinfo object.

There's a very simple solution to this problem. If compiling for Windows x64,
allocate 0x10 bytes (alignment) in the memory manager _before_ emitting any
section. That way, it's impossible to generate value RVA 0, which immediately
solves the issue.

The current workaround we use is to simply generate a simple stub type
information object in the JIT. However, this is a nasty, volatile solution,
because the compiler might someday decide to optimize it away. 

Cheers,
Stefan.

--- Appendix #1 ---

        llvm::SmallString<256> MangledName(MangleCXXRTTI);

        // Check to see if we've already declared this TypeDescriptor.
        if (llvm::GlobalVariable *GV = LLVMModule.getNamedGlobal(MangledName))
        {
                return llvm::ConstantExpr::getBitCast(GV,
llvm::Type::getInt8PtrTy(LLVMModule.getContext()));
        }

        // Compute the fields for the TypeDescriptor.
        llvm::SmallString<256> TypeInfoString(MangleCXXRTTIName);

        // Declare and initialize the TypeDescriptor.
        llvm::Constant *Fields[] = {
                getTypeInfoVTable(LLVMModule),                 // VFPtr
               
llvm::ConstantPointerNull::get(llvm::Type::getInt8PtrTy(LLVMModule.getContext())),
// Runtime data
                llvm::ConstantDataArray::getString(LLVMModule.getContext(),
TypeInfoString) };

        llvm::StructType *TypeDescriptorType =
getTypeDescriptorType(LLVMModule.getContext(), TypeInfoString);

        auto *Var = new llvm::GlobalVariable(
                LLVMModule, TypeDescriptorType, /Constant=/false,
                llvm::GlobalValue::LinkOnceODRLinkage,
                llvm::ConstantStruct::get(TypeDescriptorType, Fields),
                MangledName);

        if (Var->isWeakForLinker())
                Var->setComdat(LLVMModule.getOrInsertComdat(Var->getName()));

        return llvm::ConstantExpr::getBitCast(Var,
llvm::Type::getInt8PtrTy(LLVMModule.getContext()));


--- Appendix #2 ---

struct HandlerTypeEntry
{
        uint32_t adjectives;// 0x01: const, 0x02: volatile, 0x08: reference
        uint32_t pType;// RTTI descriptor of the exception type. 0=any
(ellipsis) (RVA ->TypeDescriptor*)
        uint32_t dispCatchObj;// rbp-based offset of the exception object in
the function stack. 0 = no object (catch by type)
        uint32_t addressOfHandler;// address of the catch handler code. returns
address where to continues execution (i.e. code after the try block) (RVA - >
void*)
        uint32_t fpDistance;// Distance Between Handler and Parent frame
pointer (RBP)
};

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20180419/4e686c07/attachment.html>


More information about the llvm-bugs mailing list