[lldb-dev] Argument unavailable and invalid pointer values

Greg Clayton gclayton at apple.com
Tue Nov 11 10:14:10 PST 2014

> On Nov 11, 2014, at 2:44 AM, Mario Zechner <badlogicgames at gmail.com> wrote:
> Hi,
> we are running into a few issues when resolving local variables. The first issue is that sometimes an argument is marked as <unavailable> by LLDB, for example __$env in frame #2 of this backtrace:
> * thread #2: tid = 0xda984, 0x000000010026d464 ThreadTest`[J]com.robovm.debug.server.apps.SleeperThread.run(__$env=0x000000010285d280, __$this=0x000000010283a8e0)V + 72 at SleeperThread.java:12, stop reason = breakpoint 1.1
>   * frame #0: 0x000000010026d464 ThreadTest`[J]com.robovm.debug.server.apps.SleeperThread.run(__$env=0x000000010285d280, __$this=0x000000010283a8e0)V + 72 at SleeperThread.java:12
>     frame #1: 0x000000010030941e ThreadTest`[j]java.lang.Runnable.run()V[Invokeinterface(java/lang/Thread)] + 9 at Thread.java:1
>     frame #2: 0x0000000100307734 ThreadTest`[J]java.lang.Thread.run(__$env=<unavailable>, __$this=0x0000000102817ab0)V + 76 at Thread.java:837
>     frame #3: 0x00000001005bb24e ThreadTest`_call0 + 142 at call0-darwin-x86_64.s:80
>     frame #4: 0x00000001005a181b ThreadTest`callVoidMethod(env=0x000000010285d280, callInfo=0x000000010528cc70) + 155 at method.c:620
>     frame #5: 0x00000001005a12da ThreadTest`rvmCallVoidInstanceMethodA(env=0x000000010285d280, obj=0x0000000102817ab0, method=0x0000000102811320, args=0x000000010528cdd0) + 634 at method.c:759
>     frame #6: 0x00000001005b9d67 ThreadTest`startThreadEntryPoint(_args=0x00007fff5fbff3e0) + 391 at thread.c:360
>     frame #7: 0x00000001005d0fc5 ThreadTest`GC_inner_start_routine(sb=0x000000010528ceb8, arg=0x0000000102863ed0) + 117 at pthread_start.c:57
>     frame #8: 0x00000001005cdeef ThreadTest`GC_call_with_stack_base(fn=0x00000001005d0f50, arg=0x0000000102863ed0) + 63 at misc.c:1860
>     frame #9: 0x00000001005d243f ThreadTest`GC_start_routine(arg=0x0000000102863ed0) + 31 at pthread_support.c:1666
>     frame #10: 0x00007fff8f66f899 libsystem_pthread.dylib`_pthread_body + 138
>     frame #11: 0x00007fff8f66f72a libsystem_pthread.dylib`_pthread_start + 137
>     frame #12: 0x00007fff8f673fc9 libsystem_pthread.dylib`thread_start + 13
> This is a context struct that gets passed to all functions in this backtrace. While it's not available for inspection in frame #2, it is available in in previous and subsequent frames (to which it gets passed by Thread.run). The argument is kept in rbx and passed to functions via rdi in the x86_64 assembler code. Any idea why it is marked as unavailable?

Because the compiler said it was unavailable in the DWARF debug info. DWARF has the ability to have a list of address ranges with locations for each range for a given variable:

Block [0x1000 - 0x2000)
    Variable "__$env" with variable value locations:
	[0x1000 - 0x1010) - rax
	[0x1020 - 0x1030) - deref(rsp + 10)

So if your function call is within the block [0x1000 - 0x2000) and the PC is not within [0x1000 - 0x1010) or [0x1020 - 0x1030), then the variable will be displayed as unavailable.

> Related to this, we sometimes get very strange pointer values for arguments. E.g. we have a breakpoint in this function:
> void _rvmHookThreadDetaching(Env* env, JavaThread* threadObj, Thread* thread, Object* throwable) {
>     fprintf(stderr, "[DEBUG] %s: Thread %lld detaching\n", LOG_TAG, threadObj->id);
> } 
> The breakpoint is a symbol breakpoint on _rvmHookThreadDetaching. Some times, threadObj has an invalid value, e.g. 0x3030303030313035, which is an invalid address, and almost seems like a sort of tomb stone value. The fun part is, that once we continue, the fprintf executes just fine, printing the value of threadObj->id, indicating that the inferior is actually using a valid address instead of the 0x3030303030313035 as reported by LLDB. We are also 100% certain that we never pass in an invalid address to this function (the caller goes on to use the threadObj value in subsequent statements, which would explode if the address was invalid).
This is again the compiler not giving you correct variable values in the DWARF. Many compilers will say that a variable is at "SP + offset" for a variable that is in the function, but that location isn't valid until the stack frame has been setup. So in some cases the compiler provides you with too generic of a location for a value. In this case the compiler just emits:

Block [0x1000 - 0x2000)
    Variable "__$env" with variable with a single location "SP + offset"

In this case, there is no location list for the variable, so it is assumed to be valid for the entire scope in which it exists [0x1000 - 0x2000)...

If you fix the compiler's DWARF debug info, it should fix things. LLDB is only as good as the info it is provided.


More information about the lldb-dev mailing list