Re: [lldb-dev] Slow expression evaluation (ASTImporter is too eager?)
Hi Jaroslav, Thank you for digging into this. I think it may be possible to not eagerly import a RecordDecl. Perhaps we could control that from clang::ASTNodeImporter::VisitPointerType and instead of a full import we could just do a minimal import for the PointeeType always. Similarly to references. But I am not sure about whether we would know during a subsequent import (where the full type is really needed) that the type had been minimally imported before. This requires some more investigation, I'll come back to you what I find, but it will take some time as this week is quite busy for me. Gabor On Tue, Nov 12, 2019 at 11:14 AM Jaroslav Sevcik wrote: > > Hi, > > thanks for the feedback, I did some more investigation and now I understand > a bit better where the LayoutRecordType calls are coming from. They are > initiated by > Clang's code generation for types, which insists on generating full LLVM > types > for any complete RecordDecl (see > > https://github.com/llvm-mirror/clang/blob/65acf43270ea2894dffa0d0b292b92402f80c8cb/lib/CodeGen/CodeGenTypes.cpp#L752 > , > the bailout for incomplete record decls is at > > https://github.com/llvm-mirror/clang/blob/master/lib/CodeGen/CodeGenTypes.cpp#L729 > ). > Ideally, clang would only emit forward declarations for any type that is > only > used as a pointer, but that is not the case at the moment. It is not quite > clear > what else we could do on the lldb side to prevent clang from emitting > types for all > those structs. At the end of this email, I am pasting a stack trace that > illustrates > the recursive emit for a pointer-chain of structs. > > There is also one additional problem with importing base classes. This one > is perhaps > more related to AST importer. Again this is best illustrated with an > example. > > struct F1 { int f1 = 30; }; > struct F0 { int f0 = 31; }; > > struct B0 { > F0 b0f; > }; > > struct C0 : B0 { > }; > > struct B1 { > F1 b1f; > int f(C0* c0); > }; > > struct C1 : B1 {}; > struct C2 { int x = 4; C1* c1 = 0; }; > > int main() { > C0 c0; > C1 c1; > C2 c2; > > return 0; // break here > } > > If we evaluate c2.x in lldb after evaluating c1 and c0, the AST importer > unnecessarily imports all the classes in this file. The main reason for > this is > that the import for structs needs to set the DefaultedDestructorIsConstexpr > bit, which is computed by looking at destructors of base classes. Looking > at > the destructors triggers completion and import of the base classes, which > in > turn might trigger more imports of base classes. In the example above, > importing C1 will cause completion and import of B1, which in turn causes > import of C0, and recursively completion and import of B0. Below is a > stack trace showing import of field F0::f0 from evaluation of c2.x. The > stack traces going through the > VisitRecordDecl-->ImportDefinition-->setBases path appear to be very hot > in the workloads we see (debugging large codebases). Below is a stack > trace that illustrates visiting F0::f0 from the evaluation of c2.x. The > question is what is the right place to break this long chain of imports. > Ideally, we would not have to import fields of C1 or B1 when evaluating > c2.x. Any ideas? > > Stack trace visiting F0::f0 from eval of c2.x, I have tried to highlight > what is imported/completed where. > > clang::ASTNodeImporter::VisitFieldDecl;; Visit F0::f0 > clang::declvisitor::Base<...>::Visit > clang::ASTImporter::ImportImpl > lldb_private::ClangASTImporter::ASTImporterDelegate::ImportImpl > clang::ASTImporter::Import > lldb_private::ClangASTImporter::CopyDecl > lldb_private::ClangASTSource::CopyDecl > lldb_private::ClangASTSource::FindExternalLexicalDecls > lldb_private::ClangASTSource::ClangASTSourceProxy::FindExternalLexicalDecls > clang::ExternalASTSource::FindExternalLexicalDecls > clang::DeclContext::LoadLexicalDeclsFromExternalStorage const > clang::DeclContext::buildLookup ;; lookup destructor > of B0 > clang::DeclContext::lookup const > clang::CXXRecordDecl::getDestructor const > clang::CXXRecordDecl::hasConstexprDestructor const > clang::CXXRecordDecl::addedClassSubobject > clang::CXXRecordDecl::addedMember > clang::DeclContext::addHiddenDecl > clang::DeclContext::addDeclInternal > clang::ASTNodeImporter::VisitFieldDecl;; visit B0::b0f > clang::declvisitor::Base<...>::Visit > clang::ASTImporter::ImportImpl > lldb_private::ClangASTImporter::ASTImporterDelegate::ImportImpl > clang::ASTImporter::Import > lldb_private::ClangASTImporter::CopyDecl > lldb_private::ClangASTSource::CopyDecl > lldb_private::ClangASTSource::FindExternalLexicalDecls > lldb_private::ClangASTSource::ClangASTSourceProxy::FindExternalLexicalDecls > clang::RecordDecl::LoadFieldsFromExternalStorage const > clang::RecordDecl::field_begin const > clang::RecordDecl::field_empty const ;; fields of B0 > clang::CXXRecordDecl::setBases > clang::ASTNodeImporter::ImportDefi
Re: [lldb-dev] Slow expression evaluation (ASTImporter is too eager?)
Hi Gabor, I was thinking about a different idea: perhaps we could try to track on lldb side which recorddecls were requested to be completed during a particular parsing session and only import full definitions if they were requested in this session. If completion was not requested in this session, we would only import forward declaration (even if we already happen to have full definition). Just like you, I have other things to attend to, so it might take some time to prototype that. I will think about your idea, it is not quite clear to me yet how it solves either of the problems. In the codegen case, it seems to be clang that walks through pointers. In the base class case we already import minimally (I think), but even minimal import causes full import of base classes (perhaps the const destructor check could only import the destructor, though). Thanks, Jaro On Thu, Nov 14, 2019 at 11:14 AM Gábor Márton wrote: > Hi Jaroslav, > > Thank you for digging into this. I think it may be possible to not eagerly > import a RecordDecl. Perhaps we could control that from > clang::ASTNodeImporter::VisitPointerType and instead of a full import we > could just do a minimal import for the PointeeType always. Similarly to > references. > But I am not sure about whether we would know during a subsequent import > (where the full type is really needed) that the type had been minimally > imported before. This requires some more investigation, I'll come back to > you what I find, but it will take some time as this week is quite busy for > me. > > Gabor > > On Tue, Nov 12, 2019 at 11:14 AM Jaroslav Sevcik wrote: > >> >> Hi, >> >> thanks for the feedback, I did some more investigation and now I >> understand >> a bit better where the LayoutRecordType calls are coming from. They are >> initiated by >> Clang's code generation for types, which insists on generating full LLVM >> types >> for any complete RecordDecl (see >> >> https://github.com/llvm-mirror/clang/blob/65acf43270ea2894dffa0d0b292b92402f80c8cb/lib/CodeGen/CodeGenTypes.cpp#L752 >> , >> the bailout for incomplete record decls is at >> >> https://github.com/llvm-mirror/clang/blob/master/lib/CodeGen/CodeGenTypes.cpp#L729 >> ). >> Ideally, clang would only emit forward declarations for any type that is >> only >> used as a pointer, but that is not the case at the moment. It is not >> quite clear >> what else we could do on the lldb side to prevent clang from emitting >> types for all >> those structs. At the end of this email, I am pasting a stack trace that >> illustrates >> the recursive emit for a pointer-chain of structs. >> >> There is also one additional problem with importing base classes. This >> one is perhaps >> more related to AST importer. Again this is best illustrated with an >> example. >> >> struct F1 { int f1 = 30; }; >> struct F0 { int f0 = 31; }; >> >> struct B0 { >> F0 b0f; >> }; >> >> struct C0 : B0 { >> }; >> >> struct B1 { >> F1 b1f; >> int f(C0* c0); >> }; >> >> struct C1 : B1 {}; >> struct C2 { int x = 4; C1* c1 = 0; }; >> >> int main() { >> C0 c0; >> C1 c1; >> C2 c2; >> >> return 0; // break here >> } >> >> If we evaluate c2.x in lldb after evaluating c1 and c0, the AST importer >> unnecessarily imports all the classes in this file. The main reason for >> this is >> that the import for structs needs to set the >> DefaultedDestructorIsConstexpr >> bit, which is computed by looking at destructors of base classes. Looking >> at >> the destructors triggers completion and import of the base classes, which >> in >> turn might trigger more imports of base classes. In the example above, >> importing C1 will cause completion and import of B1, which in turn causes >> import of C0, and recursively completion and import of B0. Below is a >> stack trace showing import of field F0::f0 from evaluation of c2.x. The >> stack traces going through the >> VisitRecordDecl-->ImportDefinition-->setBases path appear to be very hot >> in the workloads we see (debugging large codebases). Below is a stack >> trace that illustrates visiting F0::f0 from the evaluation of c2.x. The >> question is what is the right place to break this long chain of imports. >> Ideally, we would not have to import fields of C1 or B1 when evaluating >> c2.x. Any ideas? >> >> Stack trace visiting F0::f0 from eval of c2.x, I have tried to highlight >> what is imported/completed where. >> >> clang::ASTNodeImporter::VisitFieldDecl;; Visit F0::f0 >> clang::declvisitor::Base<...>::Visit >> clang::ASTImporter::ImportImpl >> lldb_private::ClangASTImporter::ASTImporterDelegate::ImportImpl >> clang::ASTImporter::Import >> lldb_private::ClangASTImporter::CopyDecl >> lldb_private::ClangASTSource::CopyDecl >> lldb_private::ClangASTSource::FindExternalLexicalDecls >> >> lldb_private::ClangASTSource::ClangASTSourceProxy::FindExternalLexicalDecls >> clang::ExternalASTSource::FindExternalLexicalDecls >> clang::DeclContext::LoadLexicalDeclsFromExternalStorage const >> cla
Re: [lldb-dev] Slow expression evaluation (ASTImporter is too eager?)
Ok, sounds good. > In the base class case we already import minimally (I think), but even minimal import causes full import This is deliberate. During construction of ASTImporter the minimal import flag is set. And then when ASTImporter::ImportDefinition is called, it will do a full import, even though minimal import is set. Otherwise we would not be able to get a full type for LLDB. > In the codegen case, it seems to be clang that walks through pointers. Yes, you are right, my idea probably would not solve that problem. But the base class related problem may be handled with that because the stack trace you sent does include clang::ASTNodeImporter::VisitPointerType. I will elaborate the idea once I found that feasible. Gabor On Thu, Nov 14, 2019 at 11:49 AM Jaroslav Sevcik wrote: > Hi Gabor, > > I was thinking about a different idea: perhaps we could try to track on > lldb side which recorddecls were requested to be completed during a > particular parsing session and only import full definitions if they were > requested in this session. If completion was not requested in this session, > we would only import forward declaration (even if we already happen to have > full definition). Just like you, I have other things to attend to, so it > might take some time to prototype that. > > I will think about your idea, it is not quite clear to me yet how it > solves either of the problems. In the codegen case, it seems to be clang > that walks through pointers. In the base class case we already import > minimally (I think), but even minimal import causes full import of base > classes (perhaps the const destructor check could only import the > destructor, though). > > Thanks, Jaro > > On Thu, Nov 14, 2019 at 11:14 AM Gábor Márton > wrote: > >> Hi Jaroslav, >> >> Thank you for digging into this. I think it may be possible to not >> eagerly import a RecordDecl. Perhaps we could control that from >> clang::ASTNodeImporter::VisitPointerType and instead of a full import we >> could just do a minimal import for the PointeeType always. Similarly to >> references. >> But I am not sure about whether we would know during a subsequent import >> (where the full type is really needed) that the type had been minimally >> imported before. This requires some more investigation, I'll come back to >> you what I find, but it will take some time as this week is quite busy for >> me. >> >> Gabor >> >> On Tue, Nov 12, 2019 at 11:14 AM Jaroslav Sevcik >> wrote: >> >>> >>> Hi, >>> >>> thanks for the feedback, I did some more investigation and now I >>> understand >>> a bit better where the LayoutRecordType calls are coming from. They are >>> initiated by >>> Clang's code generation for types, which insists on generating full LLVM >>> types >>> for any complete RecordDecl (see >>> >>> https://github.com/llvm-mirror/clang/blob/65acf43270ea2894dffa0d0b292b92402f80c8cb/lib/CodeGen/CodeGenTypes.cpp#L752 >>> , >>> the bailout for incomplete record decls is at >>> >>> https://github.com/llvm-mirror/clang/blob/master/lib/CodeGen/CodeGenTypes.cpp#L729 >>> ). >>> Ideally, clang would only emit forward declarations for any type that is >>> only >>> used as a pointer, but that is not the case at the moment. It is not >>> quite clear >>> what else we could do on the lldb side to prevent clang from emitting >>> types for all >>> those structs. At the end of this email, I am pasting a stack trace that >>> illustrates >>> the recursive emit for a pointer-chain of structs. >>> >>> There is also one additional problem with importing base classes. This >>> one is perhaps >>> more related to AST importer. Again this is best illustrated with an >>> example. >>> >>> struct F1 { int f1 = 30; }; >>> struct F0 { int f0 = 31; }; >>> >>> struct B0 { >>> F0 b0f; >>> }; >>> >>> struct C0 : B0 { >>> }; >>> >>> struct B1 { >>> F1 b1f; >>> int f(C0* c0); >>> }; >>> >>> struct C1 : B1 {}; >>> struct C2 { int x = 4; C1* c1 = 0; }; >>> >>> int main() { >>> C0 c0; >>> C1 c1; >>> C2 c2; >>> >>> return 0; // break here >>> } >>> >>> If we evaluate c2.x in lldb after evaluating c1 and c0, the AST importer >>> unnecessarily imports all the classes in this file. The main reason for >>> this is >>> that the import for structs needs to set the >>> DefaultedDestructorIsConstexpr >>> bit, which is computed by looking at destructors of base classes. >>> Looking at >>> the destructors triggers completion and import of the base classes, >>> which in >>> turn might trigger more imports of base classes. In the example above, >>> importing C1 will cause completion and import of B1, which in turn causes >>> import of C0, and recursively completion and import of B0. Below is a >>> stack trace showing import of field F0::f0 from evaluation of c2.x. The >>> stack traces going through the >>> VisitRecordDecl-->ImportDefinition-->setBases path appear to be very hot >>> in the workloads we see (debugging large codebases). Below is a stack >>> trace that illustrates visi
Re: [lldb-dev] Segfault using the lldb python module with a non-Xcode python binary
Hey António, If I understand correctly, you're trying to mix between two versions of the Python interpreter and library. That's not something that's supported and has always been an issue. Internally we get the occasional bug report where somebody install python via homebrew or python.org and the corresponding interpreter ends up first in their path because /usr/local/bin comes before /usr/bin. The same is true if you build your own LLDB, if you link against Homebrew's Python3 dylib, you need to use the Homebrew interpreter. In CMake we try really hard to ensure those two are in sync for when we run the (Python) test suite. On macOS Catalina, there's a shim for python3 in /usr/bin/ that will launch the interpreter from Xcode, which matches what the LLDB from Xcode is linked against. Given that this is an issue that comes up frequently, I'm going to add a bit of documentation about this on the LLDB website. Best, Jonas On Wed, Nov 13, 2019 at 10:53 PM António Afonso via lldb-dev wrote: > > I'm building lldb with python3 support by using the framework that is shipped > with the latest versions of Xcode. > > I'm able to build and run lldb just fine but if I try to use the lldb python > module on a python binary that is not the one from Xcode it segfaults when > creating the module. I then tried with the stock lldb from Xcode and found > the exact same issue ☹. I don’t think this was a problem before? > > > > I'm not sure why this happens and I wasn't able to debug the issue. I've > already tried with a binary that has the exact same version of python but > still the same problem: > > > > Works fine with the Xcode binary: > > $ PYTHONPATH=`lldb -P` > /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/bin/python3 > > Python 3.7.3 (default, Sep 18 2019, 14:29:06) > > [Clang 11.0.0 (clang-1100.0.33.8)] on darwin > > Type "help", "copyright", "credits" or "license" for more information. > > >>> import lldb > > >>> > > > > Fails with any other: > > $ PYTHONPATH=`lldb -P` /Users/aadsm/.pyenv/versions/3.7.3/bin/python > > Python 3.7.3 (default, Nov 12 2019, 23:19:54) > > [Clang 11.0.0 (clang-1100.0.33.8)] on darwin > > Type "help", "copyright", "credits" or "license" for more information. > > >>> import lldb > > Segmentation fault: 11 > > > > I attached lldb to see where it was failing and it's right after liblldb is > loaded and python is trying to create the module itself, in the > PyModule_Create2 function > (https://github.com/python/cpython/blob/master/Objects/moduleobject.c#L173-L179). > > The disassembly shows: > > > > Process 89097 stopped > > * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS > (code=1, address=0x10) > > frame #0: 0x00010f4cae5b Python3`PyModule_Create2 + 27 > > Python3`PyModule_Create2: > > -> 0x10f4cae5b <+27>: movq 0x10(%rax), %rdi > > 0x10f4cae5f <+31>: callq 0x10f5823b0 ; > _PyImport_IsInitialized > > 0x10f4cae64 <+36>: testl %eax, %eax > > 0x10f4cae66 <+38>: je 0x10f4cae77 ; <+55> > > Target 0: (Python) stopped. > > (lldb) dis > > Python3`PyModule_Create2: > > 0x10f4cae40 <+0>: pushq %rbp > > 0x10f4cae41 <+1>: movq %rsp, %rbp > > 0x10f4cae44 <+4>: pushq %r14 > > 0x10f4cae46 <+6>: pushq %rbx > > 0x10f4cae47 <+7>: movl %esi, %r14d > > 0x10f4cae4a <+10>: movq %rdi, %rbx > > 0x10f4cae4d <+13>: leaq 0x2226ac(%rip), %rax ; _PyRuntime > > 0x10f4cae54 <+20>: movq 0x5a0(%rax), %rax > > -> 0x10f4cae5b <+27>: movq 0x10(%rax), %rdi > > 0x10f4cae5f <+31>: callq 0x10f5823b0 ; > _PyImport_IsInitialized > > 0x10f4cae64 <+36>: testl %eax, %eax > > 0x10f4cae66 <+38>: je 0x10f4cae77 ; <+55> > > 0x10f4cae68 <+40>: movq %rbx, %rdi > > 0x10f4cae6b <+43>: movl %r14d, %esi > > 0x10f4cae6e <+46>: popq %rbx > > 0x10f4cae6f <+47>: popq %r14 > > 0x10f4cae71 <+49>: popq %rbp > > 0x10f4cae72 <+50>: jmp0x10f4cae90 ; > _PyModule_CreateInitialized > > 0x10f4cae77 <+55>: leaq 0x14f111(%rip), %rdi ; "Python import > machinery not initialized" > > 0x10f4cae7e <+62>: callq 0x10f593d40 ; Py_FatalError > > 0x10f4cae83 <+67>: nopw %cs:(%rax,%rax) > > 0x10f4cae8d <+77>: nopl (%rax) > > > > Not really sure how to debug this besides trying to build my own version of > python and see if I can repro (I don't have this issue on linux). I’ve also > checked the sys.abiflags and both binaries have the same ones. > > Has anyone experienced this before or has any pointers to debug it? > > - Afonso > > -- > Best regards, > António Afonso > ___ > lldb-dev mailing list > lldb-dev@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev ___ lldb-dev mailing list lldb-dev@lists.llvm.org https://lists
Re: [lldb-dev] Segfault using the lldb python module with a non-Xcode python binary
I've put up a patch to extend the documentation: https://reviews.llvm.org/D70252 Please have a look let me know if you have any comments or suggestions! On Thu, Nov 14, 2019 at 9:17 AM Jonas Devlieghere wrote: > > Hey António, > > If I understand correctly, you're trying to mix between two versions > of the Python interpreter and library. That's not something that's > supported and has always been an issue. Internally we get the > occasional bug report where somebody install python via homebrew or > python.org and the corresponding interpreter ends up first in their > path because /usr/local/bin comes before /usr/bin. The same is true if > you build your own LLDB, if you link against Homebrew's Python3 dylib, > you need to use the Homebrew interpreter. In CMake we try really hard > to ensure those two are in sync for when we run the (Python) test > suite. > > On macOS Catalina, there's a shim for python3 in /usr/bin/ that will > launch the interpreter from Xcode, which matches what the LLDB from > Xcode is linked against. > > Given that this is an issue that comes up frequently, I'm going to add > a bit of documentation about this on the LLDB website. > > Best, > Jonas > > On Wed, Nov 13, 2019 at 10:53 PM António Afonso via lldb-dev > wrote: > > > > I'm building lldb with python3 support by using the framework that is > > shipped with the latest versions of Xcode. > > > > I'm able to build and run lldb just fine but if I try to use the lldb > > python module on a python binary that is not the one from Xcode it > > segfaults when creating the module. I then tried with the stock lldb from > > Xcode and found the exact same issue ☹. I don’t think this was a problem > > before? > > > > > > > > I'm not sure why this happens and I wasn't able to debug the issue. I've > > already tried with a binary that has the exact same version of python but > > still the same problem: > > > > > > > > Works fine with the Xcode binary: > > > > $ PYTHONPATH=`lldb -P` > > /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.7/bin/python3 > > > > Python 3.7.3 (default, Sep 18 2019, 14:29:06) > > > > [Clang 11.0.0 (clang-1100.0.33.8)] on darwin > > > > Type "help", "copyright", "credits" or "license" for more information. > > > > >>> import lldb > > > > >>> > > > > > > > > Fails with any other: > > > > $ PYTHONPATH=`lldb -P` /Users/aadsm/.pyenv/versions/3.7.3/bin/python > > > > Python 3.7.3 (default, Nov 12 2019, 23:19:54) > > > > [Clang 11.0.0 (clang-1100.0.33.8)] on darwin > > > > Type "help", "copyright", "credits" or "license" for more information. > > > > >>> import lldb > > > > Segmentation fault: 11 > > > > > > > > I attached lldb to see where it was failing and it's right after liblldb is > > loaded and python is trying to create the module itself, in the > > PyModule_Create2 function > > (https://github.com/python/cpython/blob/master/Objects/moduleobject.c#L173-L179). > > > > The disassembly shows: > > > > > > > > Process 89097 stopped > > > > * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS > > (code=1, address=0x10) > > > > frame #0: 0x00010f4cae5b Python3`PyModule_Create2 + 27 > > > > Python3`PyModule_Create2: > > > > -> 0x10f4cae5b <+27>: movq 0x10(%rax), %rdi > > > > 0x10f4cae5f <+31>: callq 0x10f5823b0 ; > > _PyImport_IsInitialized > > > > 0x10f4cae64 <+36>: testl %eax, %eax > > > > 0x10f4cae66 <+38>: je 0x10f4cae77 ; <+55> > > > > Target 0: (Python) stopped. > > > > (lldb) dis > > > > Python3`PyModule_Create2: > > > > 0x10f4cae40 <+0>: pushq %rbp > > > > 0x10f4cae41 <+1>: movq %rsp, %rbp > > > > 0x10f4cae44 <+4>: pushq %r14 > > > > 0x10f4cae46 <+6>: pushq %rbx > > > > 0x10f4cae47 <+7>: movl %esi, %r14d > > > > 0x10f4cae4a <+10>: movq %rdi, %rbx > > > > 0x10f4cae4d <+13>: leaq 0x2226ac(%rip), %rax ; _PyRuntime > > > > 0x10f4cae54 <+20>: movq 0x5a0(%rax), %rax > > > > -> 0x10f4cae5b <+27>: movq 0x10(%rax), %rdi > > > > 0x10f4cae5f <+31>: callq 0x10f5823b0 ; > > _PyImport_IsInitialized > > > > 0x10f4cae64 <+36>: testl %eax, %eax > > > > 0x10f4cae66 <+38>: je 0x10f4cae77 ; <+55> > > > > 0x10f4cae68 <+40>: movq %rbx, %rdi > > > > 0x10f4cae6b <+43>: movl %r14d, %esi > > > > 0x10f4cae6e <+46>: popq %rbx > > > > 0x10f4cae6f <+47>: popq %r14 > > > > 0x10f4cae71 <+49>: popq %rbp > > > > 0x10f4cae72 <+50>: jmp0x10f4cae90 ; > > _PyModule_CreateInitialized > > > > 0x10f4cae77 <+55>: leaq 0x14f111(%rip), %rdi ; "Python import > > machinery not initialized" > > > > 0x10f4cae7e <+62>: callq 0x10f593d40 ; Py_FatalError > > > > 0x10f4cae83 <+67>: nopw %cs:(%rax,%rax) > > > > 0x10f4cae8d <+77>: nopl (%rax) > > > > > > > > Not really sure how to debug this besides trying to build my own version of > >