[lldb-dev] Variable shadowing

Greg Clayton via lldb-dev lldb-dev at lists.llvm.org
Wed Jun 22 14:00:19 PDT 2016


The logic is a bit wrong in my script, it should first print out the variables we have already found, followed by the one we are currently processing. The fixed script is attached:

-------------- next part --------------
A non-text attachment was scrubbed...
Name: lldbshadow.py
Type: text/x-python-script
Size: 2321 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20160622/5cf0197a/attachment-0001.bin>
-------------- next part --------------


And the output is now correct:

(lldb) check-shadow
Block: {id: 94} [0x100000f7b-0x100000f8b) (int) v = 2
is shadowed by:
Block: {id: 46} [0x100000f70-0x100000f8d) (int) v = 1


> On Jun 22, 2016, at 1:57 PM, Greg Clayton via lldb-dev <lldb-dev at lists.llvm.org> wrote:
> 
> You can currently do this by checking for other variables to see if any names match.
> 
> In python when stopped in the function below you can do use the API:
> 
> 
> (lldb) script
> Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>>> frame_vars = lldb.frame.GetVariables(True, True, True, True)
>>>> print frame_vars
> (int) v = 1
> (int) v = 2
> 
> frame_vars is a list of all variables in the current stack frame. They are ordered correctly so you see your first "v" first and the second one next.
> 
> Lets grab the exact lexical block from the current frame:
> 
>>>> block = lldb.frame.GetBlock()
> 
> This is the block from line 4 - 7 in your source code.
> 
>>>> print block.GetVariables(lldb.frame, True, True, True, 0)
> (int) v = 2
> 
> Note that if we ask the block for its variables, it will only have the variables contained in that block. Now you can ask "block" for its parent block:
> 
>>>> print block.GetParent().GetVariables(lldb.frame, True, True, True, 0)
> (int) v = 1
> 
> 
> So with all of this you could create a new python command:
> 
> 
> #!/usr/bin/python
> 
> import lldb
> import shlex
> 
> @lldb.command("check-shadow")
> def check_shadow_command(debugger, command, result, dict):
>    target = debugger.GetSelectedTarget()
>    if not target:
>        print >>result, "invalid target"
>        return
>    process = target.GetProcess()
>    if not process:
>        print >>result, "invalid process"
>        return
>    thread = process.GetSelectedThread()
>    if not thread:
>        print >>result, "invalid thread"
>        return
>    frame = thread.GetSelectedFrame()
>    if not frame:
>        print >>result, "invalid frame"
>        return
>    # Parse command line args
>    command_args = shlex.split(command)
>    # TODO: add support for using arguments that are passed to this command...
> 
>    # Make a dictionary of variable name to "SBBlock and SBValue"
>    var_dict = {}
> 
>    # Get the deepest most block from the current frame
>    block = frame.GetBlock()
>    # Iterate through the block and all of its parents
>    while block.IsValid():
>        # Get block variables from the current block only
>        block_vars = block.GetVariables(frame, True, True, True, 0)
>        # Iterate through all variables in the current block
>        for block_var in block_vars:
>            # Get the variable name and see if we already have a variable by this name?
>            block_var_name = block_var.GetName()
>            if block_var_name in var_dict:
>                # We already have seen a variable with this name, so it is shadowed
>                print block, block_var
>                print 'is shadowed by:'
>                shadow_block_and_vars = var_dict[block_var_name]
>                for shadow_block_and_var in shadow_block_and_vars:
>                    print shadow_block_and_var[0], shadow_block_and_var[1]
>            # Since we can have multiple shadowed variables, we our variable
>            # name dictionary to have an array or "block + variable" pairs so
>            # We can correctly print out all shadowed variables and whow which
>            # blocks they come from
>            if block_var_name in var_dict:
>                var_dict[block_var_name].append([block, block_var])
>            else:
>                var_dict[block_var_name] = [[block, block_var]]
>        # Get the parent block and continue 
>        block = block.GetParent()
> 
> 
> 
> 
> I have attached this as a script that you can import:
> 
> <lldbshadow.py>
> 
> 
> Then you can run this:
> 
> 
> % lldb a.out 
> (lldb) command script import /tmp/lldbshadow.py
> (lldb) target create "a.out"
> (lldb) b main.cpp:6
> (lldb) run
> Process 423 stopped
> * thread #1: tid = 0x46a88f, 0x0000000100000f82 a.out foo() + 18, stop reason = breakpoint 1.1, queue = com.apple.main-thread
>    frame #0: 0x0000000100000f82 a.out foo() + 18 at main.cpp:6
>   3   	    int v = 1;
>   4   	    {
>   5   	        int v = 2;
> -> 6   	        ++v;
>   7   	    }
>   8   	}
>   9   	
> 
> (lldb) check-shadow
> Block: {id: 46} [0x100000f70-0x100000f8d) (int) v = 1
> is shadowed by:
> Block: {id: 94} [0x100000f7b-0x100000f8b) (int) v = 2
> 
> So yes it is possible, and I have attached an example. Adding a function to SBValue might not make sense because SBValue objects are used to represent registers and many other things other than local variables, and there is no language agnostic rule we could use to implement this correctly at the generic API level.
> 
> Greg Clayton
> 
>> On Jun 22, 2016, at 9:43 AM, Bogdan Hopulele via lldb-dev <lldb-dev at lists.llvm.org> wrote:
>> 
>> Hi all,
>> 
>> I’m using lldb 3.9 through the C++ API and I’m trying to determine if a local variable is shadowed or not with no luck.
>> For the code below:
>> 
>> 1.       Is there an API call, that I somehow missed, that can tell me that (v = 2) shadows (v = 1)?
>> 2.       Can I rely on their order in the SBValueList object?
>> 3.       Would you guys think it would be worth adding bool SBValue::IsShadowed() const ?
>> 
>> 
>> 1 void foo()
>> 2 {
>>      3     int v = 1;
>>      4     {
>>      5           int v = 2;
>> -->   6           ++v;
>>      7     }
>> 8 }
>> 
>> Thank,
>> Bogdan
>> National Instruments Romania S.R.L.
>> ------------------------------------------------------
>> B-dul 21 Decembrie 1989, nr. 77, A2
>> Cluj-Napoca 400604, Romania
>> C.I.F.: RO17961616 | O.R.C.: J12/3337/2005
>> Telefon: +40 264 406428 | Fax: +40 264 406429
>> E-mail: office.cluj at ni.com 
>> Web: romania.ni.com 
>> 
>> Vanzari si suport tehnic:
>> Telefon gratuit : 0800 070071
>> E-mail vanzari: ni.romania at ni.com
>> E-mail suport tehnic: techsupport at ni.com _______________________________________________
>> lldb-dev mailing list
>> lldb-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
> 
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev



More information about the lldb-dev mailing list