Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assertion of emitLocation causes BAD_ACCESS fault #42925

Closed
tonybaloney opened this issue Sep 30, 2020 · 32 comments
Closed

Assertion of emitLocation causes BAD_ACCESS fault #42925

tonybaloney opened this issue Sep 30, 2020 · 32 comments
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner

Comments

@tonybaloney
Copy link
Contributor

Description

The JIT is being used to compile some custom instructions from a project (https://github.com/microsoft/pyjion) and I'm working on updating it from .NET Core 1.0.0rc2 all the way to .NET 5. The branch in question is here microsoft/Pyjion#237

The emitter causes a bad access fault during the unwind phase:

bool Valid() const
    {
        // Things we could validate:
        //   1. the instruction group pointer is non-nullptr.
        //   2. 'ig' is a legal pointer to an instruction group.
        //   3. 'codePos' is a legal offset into 'ig'.
        // Currently, we just do #1.
        // #2 and #3 should only be done in DEBUG, if they are implemented.

>>  if (ig == nullptr)
        {
            return false;
        }

        return true;
    }

Exception: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

This is because emitLocation is an invalid memory address. Its being called from here:

UNATIVE_OFFSET emitLocation::CodeOffset(emitter* emit) const
{
    assert(Valid());
    return emit->emitCodeOffset(ig, codePos);
}

In the case of the fault, it happens in assert(Valid()), not because the assertion fails, but because it cannot read from the emitLocation because it is an invalid memory address.
There is no assertion prior to this point to validate the emitLocation pointer, causing a crash.

Configuration

  • .NET 5.0 (release/5.0) compiled from source in debug configuration
  • macOS 10.15.7

CLR Flags

CORJIT_FLAG_SKIP_VERIFICATION
CORJIT_FLAG_DEBUG_CODE
CORJIT_FLAG_NO_INLINING
CORJIT_FLAG_MIN_OPT

JIT Settings

JitLsraStats= 1;
DumpJittedMethods = 1;
JitDumpToDebugger = 1;
JitDumpASCII = 1;
JitDump = u"methodname"

Regression?

This previously worked in .NET core 1.0.0rc2 (sorry!)

Other information

Stack trace

emitLocation::Valid() const emit.h:183
emitLocation::CodeOffset(emitter*) const emit.cpp:44
Compiler::unwindEmitFuncHelper(FuncInfoDsc*, void*, void*, bool) unwindamd64.cpp:766
Compiler::unwindEmitFunc(FuncInfoDsc*, void*, void*) unwindamd64.cpp:883
Compiler::unwindEmit(void*, void*) unwindamd64.cpp:736
CodeGen::genEmitUnwindDebugGCandEH() codegencommon.cpp:2396
CodeGenPhase::DoPhase() codegen.h:1605
Phase::Run() phase.cpp:61
DoPhase(CodeGen*, Phases, void (CodeGen::*)()) codegen.h:1619
CodeGen::genGenerateCode(void**, unsigned int*) codegencommon.cpp:2053
Compiler::compCompile(void**, unsigned int*, JitFlags*) compiler.cpp:4942
Compiler::compCompileHelper(CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*) compiler.cpp:6129
Compiler::compCompile(CORINFO_MODULE_STRUCT_*, void**, unsigned int*, JitFlags*)::$_12::operator()(Compiler::compCompile(CORINFO_MODULE_STRUCT_*, void**, unsigned int*, JitFlags*)::__JITParam*) const compiler.cpp:5468
Compiler::compCompile(CORINFO_MODULE_STRUCT_*, void**, unsigned int*, JitFlags*) compiler.cpp:5487
jitNativeCode(CORINFO_METHOD_STRUCT_*, CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*, void*)::$_15::operator()(jitNativeCode(CORINFO_METHOD_STRUCT_*, CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*, void*)::__JITParam*) const::'lambda'(jitNativeCode(CORINFO_METHOD_STRUCT_*, CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*, void*)::$_15::operator()(jitNativeCode(CORINFO_METHOD_STRUCT_*, CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*, void*)::__JITParam*) const::__JITParam*)::operator()(jitNativeCode(CORINFO_METHOD_STRUCT_*, CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*, void*)::$_15::operator()(jitNativeCode(CORINFO_METHOD_STRUCT_*, CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*, void*)::__JITParam*) const::__JITParam*) const compiler.cpp:6771
jitNativeCode(CORINFO_METHOD_STRUCT_*, CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*, void*)::$_15::operator()(jitNativeCode(CORINFO_METHOD_STRUCT_*, CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*, void*)::__JITParam*) const compiler.cpp:6796
jitNativeCode(CORINFO_METHOD_STRUCT_*, CORINFO_MODULE_STRUCT_*, ICorJitInfo*, CORINFO_METHOD_INFO*, void**, unsigned int*, JitFlags*, void*) compiler.cpp:6798
CILJit::compileMethod(ICorJitInfo*, CORINFO_METHOD_INFO*, unsigned int, unsigned char**, unsigned int*) ee_il_dll.cpp:273
ILGenerator::compile(ICorJitInfo*, ICorJitCompiler*, int) ilgen.h:486
PythonCompiler::emit_compile() pycomp.cpp:1124
AbstractInterpreter::compile_worker() absint.cpp:2650
AbstractInterpreter::compile() absint.cpp:3039
Jit_EvalTrace(PyjionJittedCode*, _frame*) pyjit.cpp:368
PyJit_EvalFrame(_ts*, _frame*, int) pyjit.cpp:520
_PyEval_EvalCode 0x0000000104258523
PyEval_EvalCode 0x000000010424e9ab
PyRun_InteractiveOneObjectEx 0x00000001042a0df9
PyRun_InteractiveLoopFlags 0x00000001042a0502
PyRun_AnyFileExFlags 0x00000001042a03ec
Py_RunMain 0x00000001042bdada
pymain_main 0x00000001042bdc3f
Py_BytesMain 0x00000001042bde3b
main python.c:15
start 0x00007fff6745bcc9

stdout/err

CLFLG_MINOPT set for method modulename:methodname(long,long):long
IL Code Size,Instr  131,  55, Basic Block count   6, Local Variable Num,Ref count   6, 10 for method modulename:methodname(long,long):long
IL Code Size,Instr  131,  55, Basic Block count   6, Local Variable Num,Ref count   6, 10 for method modulename:methodname(long,long):long
----------
LSRA Stats
----------
Total Tracked Vars:  0
Total Reg Cand Vars: 0
Total number of Intervals: 36
Total number of RefPositions: 135
Total Spill Count: 0    Weighted: 0
Total CopyReg Count: 0   Weighted: 0
Total ResolutionMov Count: 0    Weighted: 0
Total number of split edges: 0
Total Number of spill temps created: 0

Exception: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner labels Sep 30, 2020
@AndyAyersMS
Copy link
Member

Compiler::unwindEmitFuncHelper
{
        ...
        if (func->startLoc == nullptr)
        {
            startOffset = 0;
        }
        else
        {
            startOffset = func->startLoc->CodeOffset(GetEmitter());
        }

seems a little odd we end up calling CodeOffset with a null startLoc.

Can you add repro instructions? Does this repro every time?

@tonybaloney
Copy link
Contributor Author

@AndyAyersMS func->startLoc wasn't NULL, it was a very high memory (and invalid) address. I tried stepping back and setting func->startLoc to 0 from the debugger, but the next condition (func->endLoc) faults with exactly the same issue (invalid memory address).

(lldb) e func->startLoc
(emitLocation *) $0 = 0x8d48e38b49000000
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 11.1
  * frame #0: 0x00000001086c9524 libclrjit.dylib`Compiler::unwindEmitFuncHelper(this=0x00007f98bf7e5018, func=0x00007f98bf7ed1c0, pHotCode=0x00007f98bf7ed1c0, pColdCode=0x0000000000000000, isHotCode=true) at unwindamd64.cpp:760:13
    frame #1: 0x00000001086c94aa libclrjit.dylib`Compiler::unwindEmitFunc(this=0x00007f98bf7e5018, func=0x00007f98bf7ed1c0, pHotCode=0x00007f98bf7ed1c0, pColdCode=0x0000000000000000) at unwindamd64.cpp:883:5
    frame #2: 0x00000001086c9453 libclrjit.dylib`Compiler::unwindEmit(this=0x00007f98bf7e5018, pHotCode=0x00007f98bf7ed1c0, pColdCode=0x0000000000000000) at unwindamd64.cpp:736:9

(lldb) reg r
General Purpose Registers:
       rax = 0x00007f98bf7e5018
       rbx = 0x0000000000000040
       rcx = 0x0000000000000000
       rdx = 0x00007f98bf7ed1c0
       rdi = 0x00007f98bf7e5018
       rsi = 0x00007f98bf7ed1c0
       rbp = 0x00007ffee7ed0b50
       rsp = 0x00007ffee7ed0ac0
        r8 = 0x0000000000000001
        r9 = 0x000000010883ba00  "'"'"
       r10 = 0x0000000000000001
       r11 = 0x00007ffee7ed09d0
       r12 = 0x0000000000000000
       r13 = 0x00007f98c0a42240
       r14 = 0x0000000000000000
       r15 = 0x00007f98c08ca9a0
       rip = 0x00000001086c9524  libclrjit.dylib`Compiler::unwindEmitFuncHelper(FuncInfoDsc*, void*, void*, bool) + 68 at unwindamd64.cpp:760:13
    rflags = 0x0000000000000202
        cs = 0x000000000000002b
        fs = 0x0000000000000000
        gs = 0x0000000000000000

I thought this maybe PIC/PIE related, but the caller to the JIT compiled with -fPIC, same as .NET

@AndyAyersMS
Copy link
Member

The FuncInfoDscs get zero filled initially by fgCreateFunclets, and from what I can tell, startLoc is only ever set over in unwindGetFuncLocations to a malloc`d value.

So the failure you're seeing above seems like it could be some sort of memory corruption. Does it always fail the same way?

@tonybaloney
Copy link
Contributor Author

this repros every time in exactly the same way. this is a library using the JIT (CILJit::compileMethod) as a replacement compiler for Python, not via the CLR microsoft/Pyjion#237.

repro steps:

$ python3.9
 >>> import pyjion
 >>> pyjion.enable()
 >>> a = 1
CLFLG_MINOPT set for method modulename:methodname(long,long):long
IL Code Size,Instr  131,  55, Basic Block count   6, Local Variable Num,Ref count   6, 10 for method modulename:methodname(long,long):long
IL Code Size,Instr  131,  55, Basic Block count   6, Local Variable Num,Ref count   6, 10 for method modulename:methodname(long,long):long
----------
LSRA Stats
----------
Total Tracked Vars:  0
Total Reg Cand Vars: 0
Total number of Intervals: 36
Total number of RefPositions: 135
Total Spill Count: 0    Weighted: 0
Total CopyReg Count: 0   Weighted: 0
Total ResolutionMov Count: 0    Weighted: 0
Total number of split edges: 0
Total Number of spill temps created: 0

Exception: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

@AndyAyersMS
Copy link
Member

Ok, let me see if I can repro.

@tonybaloney
Copy link
Contributor Author

Wow! thank you. I can put a breakpoint into Compiler::fgCreateFunclets() and dump the thread state if that's any help?

@tonybaloney
Copy link
Contributor Author

tonybaloney commented Oct 1, 2020

Some additional steps for setup:

  • Deep clone (CoreCLR is a submodule) the branch
  • Compile CoreCLR (so that CoreCLR/artifacts/bin/coreclr/${CLR_OS_BUILD}/inc headers are available and CoreCLR/artifacts/bin/coreclr/OSX.x64.Debug/libclrjit.dylib can be linked)
  • Build the project to create the Python module cmake-build-debug/pyjion.so
  • Start Python3.9 (I'm using rc2) from that path and import the module.
  • Enable the JIT
  • Type anything at the REPL

@AndyAyersMS
Copy link
Member

Build the project to create the Python module cmake-build-debug/pyjion.so

What exactly do I need to do for this step? cmake seemingly needs some sort of arguments.

@AndyAyersMS
Copy link
Member

Never mind, figured it out... looks like I can repro (?):

Python 3.9.0rc2 (v3.9.0rc2:2bd31b5fde, Sep 16 2020, 20:19:18) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyjion
>>> pyjion.enable()
True
>>> a = 1
Tracing <module> from <stdin> line 1 #1 (0 failures so far)
Calling first <module> from <stdin> line 1 0x7f9f7e527050
Processing OPCODE LOAD_CONST
Processing OPCODE STORE_NAME
Processing OPCODE LOAD_CONST
Processing OPCODE RETURN_VALUE
Bus error: 10

@AndyAyersMS
Copy link
Member

Debugging, my error looks a bit different than the one you reported above, but perhaps they're related. In both cases the emitter is failing.

You need to implement CorJitIInfo::allocMem. In particular, you need to allocate memory for the jit to use when writing out the compiled code and data, so hotCodeBlock and roDataBlock must be set to writeable memory of proper extent.

Ideally code and data blocks also have the requested alignment, and the code block should also be executable.

@tonybaloney
Copy link
Contributor Author

@AndyAyersMS aha!! that makes sense and explains the corrupt memory address. I've implemented it using Python's pool-based memory allocator, which has an alignment of 16 (fixed).

It doesn't crash anymore, but it raises an exception. This one is much more verbose so I'll keep shaving this yak :-)

>>> a=1
a=1
Tracing <module> from <stdin> line 1 #1 (0 failures so far)

Calling first <module> from <stdin> line 1 0x7fc213c0df80

Processing OPCODE LOAD_CONST
Processing OPCODE STORE_NAME
Processing OPCODE LOAD_CONST
Processing OPCODE RETURN_VALUE
CLFLG_MINOPT set for method modulename:methodname(long,long):long
IL Code Size,Instr  131,  55, Basic Block count   6, Local Variable Num,Ref count   6, 10 for method modulename:methodname(long,long):long
IL Code Size,Instr  131,  55, Basic Block count   6, Local Variable Num,Ref count   6, 10 for method modulename:methodname(long,long):long
----------
LSRA Stats
----------
Total Tracked Vars:  0
Total Reg Cand Vars: 0
Total number of Intervals: 36
Total number of RefPositions: 135
Total Spill Count: 0    Weighted: 0
Total CopyReg Count: 0   Weighted: 0
Total ResolutionMov Count: 0    Weighted: 0
Total number of split edges: 0
Total Number of spill temps created: 0

Assert: /Users/anthonyshaw/CLionProjects/pyjion/CoreCLR/src/coreclr/src/jit/unwindamd64.cpp 807Assert: /Users/anthonyshaw/CLionProjects/pyjion/CoreCLR/src/coreclr/src/jit/unwindamd64.cpp 857count:        743, size:      64398, max =       2424
allocateMemory:     131072, nraUsed:      66840

Alloc'd bytes by kind:
                  kind |       size |     pct
  ---------------------+------------+--------
         AssertionProp |          0 |   0.00%
               ASTNode |      14312 |  22.22%
              InstDesc |       6464 |  10.04%
              ImpStack |       2448 |   3.80%
            BasicBlock |       2288 |   3.55%
             fgArgInfo |        432 |   0.67%
       fgArgInfoPtrArr |         48 |   0.07%
              FlowList |        288 |   0.45%
     TreeStatementList |          0 |   0.00%
               SiScope |          0 |   0.00%
       DominatorMemory |          0 |   0.00%
                  LSRA |       2988 |   4.64%
         LSRA_Interval |       2960 |   4.60%
      LSRA_RefPosition |       8704 |  13.52%
          Reachability |          0 |   0.00%
                   SSA |          0 |   0.00%
           ValueNumber |          0 |   0.00%
              LvaTable |       1920 |   2.98%
            UnwindInfo |          0 |   0.00%
                hashBv |        240 |   0.37%
                bitset |        232 |   0.36%
          FixedBitVect |         24 |   0.04%
               Generic |       1244 |   1.93%
   LocalAddressVisitor |          0 |   0.00%
         FieldSeqStore |          0 |   0.00%
    ZeroOffsetFieldMap |         40 |   0.06%
          ArrayInfoMap |          0 |   0.00%
          MemoryPhiArg |          0 |   0.00%
                   CSE |          0 |   0.00%
                    GC |       1448 |   2.25%
       CorTailCallInfo |          0 |   0.00%
              Inlining |        128 |   0.20%
            ArrayStack |          0 |   0.00%
             DebugInfo |          0 |   0.00%
             DebugOnly |      15158 |  23.54%
               Codegen |       1184 |   1.84%
               LoopOpt |          0 |   0.00%
             LoopHoist |          0 |   0.00%
               Unknown |       1848 |   2.87%
            RangeCheck |          0 |   0.00%
              CopyProp |          0 |   0.00%
           SideEffects |          0 |   0.00%
       ObjectAllocator |          0 |   0.00%
    VariableLiveRanges |          0 |   0.00%
           ClassLayout |          0 |   0.00%
       TailMergeThrows |          0 |   0.00%
             EarlyProp |          0 |   0.00%
              ZeroInit |          0 |   0.00%

Got failure code from JIT.Compiling failed <module> from <stdin> line 1

Tracing <module> from <stdin> line 1 

Compilation failure #1

>>> 

@AndyAyersMS
Copy link
Member

I looked at this next failure a bit but ended up wondering what IL was being emitted, and got distracted trying to figure out why I couldn't enable regular jit dumps (which among other things would show the IL). I think there's something off with the implementation of getStringConfigValue in the jit host. I suspect maps that use const uint16_t* as keys likely won't work when the strings are passed cross-library; I think the map will need to use something like std::u16string as the key type to ensure the lookup is comparing string contents instead of string addresses.

It would also probably be worthwhile to read the environment variables looking for COMPlus_ settings and make those available to the jit.

@tonybaloney
Copy link
Contributor Author

Ah yes thanks. Made that change microsoft/Pyjion@30d8423

Can't see the JitDump yet but I can tell that its matching the values correctly

@tonybaloney
Copy link
Contributor Author

I'm stuck on

void Compiler::unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pColdCode, bool isHotCode)
{
      ...
      assert(fgFirstColdBlock != nullptr);

The firstColdBlock is a nullptr. I'm not sure where it gets that address from?
I think its related to another bug I found around popping' basic frame blocks from the CPython "IL".

@AndyAyersMS
Copy link
Member

Are you emitting IL with EH regions / opcodes? We would not expect to be looking for cold blocks/funclets unless there was some kind of EH.

That's the question I was trying to ask when I got sidetracked with enabling dumping.

@tonybaloney
Copy link
Contributor Author

Yes, thats in absint.h/absint.cpp.

I'm trying to revitalise this 4-year old code base, so there have also been some major changes to CPython's opcodes

@AndyAyersMS
Copy link
Member

To get dumping working, you need to return FALSE from logMsg

****** START compiling modulename:methodname(long,long):long (MethodHash=643c0b67)
Generating code for Unix x64
OPTIONS: compCodeOpt = BLENDED_CODE
OPTIONS: compDbgCode = true
OPTIONS: compDbgInfo = false
OPTIONS: compDbgEnC  = false
OPTIONS: compProcedureSplitting   = false
OPTIONS: compProcedureSplittingEH = false
IL to import:
IL_0000  03                ldarg.1     
IL_0001  20 68 00 00 00    ldc.i4       0x68
IL_0006  d3                conv.i      
IL_0007  58                add         
IL_0008  0a                stloc.0     
IL_0009  03                ldarg.1     
IL_000a  28 41 00 00 00    call         0x41
IL_000f  21 30 a9 1c 0e 01 00 00 00 ldc.i8       0xE1CA930
...

@AndyAyersMS
Copy link
Member

To fix the asserts, only allocate the cold block and ro data block if the sizes are nonzero:

    if (coldCodeSize > 0)
    {
        *coldCodeBlock = PyMem_Malloc(coldCodeSize);
    }
    if (roDataSize > 0)
    {
             *roDataBlock = PyMem_Malloc(roDataSize);
    }

otherwise the jit gets confused and thinks there should be cold code.

@AndyAyersMS
Copy link
Member

To get past the "jit failed" you need to set the OS type in getEEInfo. Since you're on a mac, set it to unix for now:

pEEInfoOut->osType = CORINFO_UNIX;

With the above fixes it looks like it's trying to run the jitted code, but still no joy:

'****** DONE compiling modulename:methodname(long,long):long
Tracing <module> from <stdin> line 1 
Invoking trace <module> from <stdin> line 1 0x0 0x10f14eb30
Segmentation fault: 11

@tonybaloney
Copy link
Contributor Author

Ah yes, thats a "feature" of the PyMem_Alloc functions, they allocate 0-size blocks as a way of better handling null-references

@tonybaloney
Copy link
Contributor Author

That all worked! I'm up to the SEG fault but with the breakpoints, I can see it hasn't properly resolved the code address. There are still some failing assertions but I've put warnings on all the unimplemented methods to better get an idea on the issue

.NET failed assertion: /Users/anthonyshaw/CLionProjects/pyjion/CoreCLR/src/coreclr/src/jit/codegenxarch.cpp 8268.
NET failed assertion: /Users/anthonyshaw/CLionProjects/pyjion/CoreCLR/src/coreclr/src/jit/emitxarch.cpp 7179Converting emitMaxStackDepth from bytes (0) to elements (0)
.NET failed assertion: /Users/anthonyshaw/CLionProjects/pyjion/CoreCLR/src/coreclr/src/jit/emitxarch.cpp 12698
allocUnwindInfo not implemented 

@tonybaloney
Copy link
Contributor Author

What does void *getHelperFtn(CorInfoHelpFunc ftnNum, void **ppIndirection) do? it looks important

@tonybaloney
Copy link
Contributor Author

This getHelperFtn seems related to .NET failed assertion: /Users/anthonyshaw/CLionProjects/pyjion/CoreCLR/src/coreclr/src/jit/codegenxarch.cpp 8268.. It seems to want a function pointer back

compiler->compGetHelperFtn((CorInfoHelpFunc)helper, &pAddr

@tonybaloney
Copy link
Contributor Author

Figured out I can just return (void*)0x1001; from getHelperFtn for now and there are no more assertion failures!

@tonybaloney
Copy link
Contributor Author

Nearly there the recordCallSite isn't implemented, so the code address is still a null pointer

@tonybaloney
Copy link
Contributor Author

@AndyAyersMS try microsoft/Pyjion@1a09ff1 I've set the right pointer to the hot code address. It doesn't execute (faults with bad access), so maybe the memory is allocated with the wrong flags, or its the wrong size

@tonybaloney
Copy link
Contributor Author

Screen Shot 2020-10-02 at 12 21 15 pm

The pointer looks ok, this looks like executable code

@AndyAyersMS
Copy link
Member

What does void *getHelperFtn do...

It gives the jit the address of a helper method. If you look at the jitted code one of the first things is

call     CORINFO_HELP_STACK_PROBE

and the jit is asking the runtime for the address of this helper. For this helper, you can return the address of a do-nothing void f() {} and it may work for a time.

The memory you allocate for the jit needs to have execute permissions; normally allocated blocks don't have this. I don't know the python hosting API well enough to know if there's something you can use. Also OSX may be finicky about giving out pages that are both writeable and executable.

@tonybaloney
Copy link
Contributor Author

@AndyAyersMS I saw that VirtualAlloc() is implemented cross-platform and part of the PAL APIs, but I can't see where the symbol gets built so I can link it and use that function to allocate executable memory

@tonybaloney
Copy link
Contributor Author

@AndyAyersMS it works now :-) feel free to give it a go! there's loads of bugs but its evaluating the JIT'ed code on OSX and interacting with the CPython methods.

@tonybaloney
Copy link
Contributor Author

Screen Shot 2020-10-02 at 2 33 41 pm

Thanks for your help Andy! We can close this issue now. I'm going to keep chipping away at this thing but this has been really helpful and now its executing for me (only simple statements)

@AndyAyersMS
Copy link
Member

Very cool! Glad to help.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

3 participants