Search code examples
c++debuggingglobal-variableslldb

LLDB - printing contents of a static variable inside function


I've got the following code that define an Instance method in static class.

namepsace AAA { 
class BBB { 
   static BBB& Instance() { 
       static BBB bbb();
       return bbb;
   }
}

I'd like to print the static object bbb from any breakpoint in the code (since it's static, it should be defined anywhere in the code)

If I lookup the symbol using the following command, it gives me the symbol's offset in the binary file. However, it might not include the ASLR (Address Space Layout Randomization) offset.

The ASLR offset can be obtained by by subtracting the address of a function symbol from its offset in the binary structure (assuming that the function and the static share the same ASLR).

the outcome ASLR value should be added to the symbol's offset to get its real place in the process memory.

I wonder if there's an easier way to find the memory location of this static variable ? if not perhaps there's way to automate this instruction set?

Thanks


Solution

  • There are two problems with function statics in the debugger.

    The first is that they are hard to find since you have to dig into debug information pretty deeply, so a "please find me a function static" request needs to have some kind of scope or it would behave badly in big apps.

    So we need some kind of scoping here. The second problem is that though the symbol name could convey that scoping, the demangled names of function statics aren't identifiers that the C++ language can parse to valid code that fetches the value. So you can't use them in the expression parser.

    lldb should add some more syntax to the target variable command to specify function scopes, that would be fairly straightforward and allow you to specify the scope. This comes up every so often as an enhancement request, but hasn't achieved activation energy yet...

    However, these statics still have mangled names - and lldb's expression parser will do lookup of symbols by mangled name when they appear in an expression. The one trick here is that bare symbols don't have types, just addresses. So you have to provide the type. But that's easily done...

    In your example (I changed the name from bbb to local_bbb to make it easier to find) first I have to find the mangled name:

    (lldb) image dump symtab <binary_name> -m
    ...
    [   26]    115 D X Data            0x0000000100008000 0x0000000100008000 0x0000000000000020 0x000f0080 _ZZN3AAA3BBB8InstanceEvE9local_bbb
    
    [   27]    116 D X Data            0x0000000100008020 0x0000000100008020 0x0000000000000008 0x000f0080 _ZGVZN3AAA3BBB8InstanceEvE9local_bbb
    

    It's a little odd that there are two, why is that?

    (lldb) lang cplus demangle _ZGVZN3AAA3BBB8InstanceEvE9local_bbb
    _ZGVZN3AAA3BBB8InstanceEvE9local_bbb ---> guard variable for AAA::BBB::Instance()::local_bbb
    

    Ah, that's the guard variable for setting the static. So we want the other one. Then I can access that symbol using a cast to provide the type info:

    (lldb) expr (AAA::BBB &) _ZZN3AAA3BBB8InstanceEvE9local_bbb
    (AAA::BBB) $2 = (an_int = 200, a_string = "some value")
    

    I also added some fields to show we were getting the value right... Because lldb's handling going from the symbol name to the address it will get the ASLR slides right for you.