I found an issue where the expression evaluation doesn't work (for non trivial exprs) when the leak sanitizer is enabled in the process being debugged.
lldb defaults to interpertation because it thinks it can't JIT it (and most interesting exprs can't be interpreted). The JIT check fails because calling the process's mmap fails.
I debugged the InferiorCallMmap function to figure this out. This function finds all functions with mmap name in it and executes the first one in that list.
When asan is enabled (and by default on linux it turns on the leak sanitizer) it introduces a new mmap symbol in the binary (the only that will be called instead of the real one). This can be found here: https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_wrappers.cpp#L155-L160. And there is also another new function named __interceptor_mmap which registers the call for the sanitizer I think. You can find that one here (I think): https://github.com/llvm/llvm-project/blob/6148cca70888ead020a808279043fd013ca72a2a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc#L7304-L7313.
When lldb calls the redefined mmap it will return -1 but will be able to allocate memory if it calls the ___interceptor_mmap though. Both functions end up calling __internal_mmap but the big difference between the two is that the redefined mmap also checks the return of internal_mmap with internal_iserror and will return -1 when it fails the check. Here's the code for that: https://github.com/llvm/llvm-project/blob/6148cca70888ead020a808279043fd013ca72a2a/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc#L83-L90. Not really sure why to be honest. I tried to debug but it was not simple inside the ThreadPlanCallFunction, I tried to enable SINGLE_STEP_EXPRESSIONS but then the process kind of dies on me.
I came up with a simple fix to get around this which is to try each mmap we find (and not only the first one) until we find one that works. Another possible solution is to see if internal_mmap exists and call that one if it does.. I feel it's a bit more implementation dependent though, while the loop sounds more future proof (I'm assuming calling a bunch of mmaps until one actually works won't launch missiles).
(This implemention is not final, it should be possible to move a bunch of things out of the loop I believe)
Not really sure who to add for review so adding a few people I've seen in the code.