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:

#!/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
                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]
                print 'is shadowed by:'
                print block, block_var
            # 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()
    


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@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@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.c...@ni.com 
>> Web: romania.ni.com 
>> 
>> Vanzari si suport tehnic:
>> Telefon gratuit : 0800 070071
>> E-mail vanzari: ni.roma...@ni.com
>> E-mail suport tehnic: techsupp...@ni.com 
>> _______________________________________________
>> lldb-dev mailing list
>> lldb-dev@lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
> 
> _______________________________________________
> lldb-dev mailing list
> lldb-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

_______________________________________________
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

Reply via email to