Greg Clayton | fe9d1ee | 2016-06-23 19:54:32 +0000 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | |
| 3 | import lldb |
| 4 | import shlex |
| 5 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 6 | |
Greg Clayton | fe9d1ee | 2016-06-23 19:54:32 +0000 | [diff] [blame] | 7 | @lldb.command("shadow") |
Greg Clayton | 296f166 | 2016-06-28 00:06:35 +0000 | [diff] [blame] | 8 | def check_shadow_command(debugger, command, exe_ctx, result, dict): |
| 9 | '''Check the currently selected stack frame for shadowed variables''' |
| 10 | process = exe_ctx.GetProcess() |
| 11 | state = process.GetState() |
| 12 | if state != lldb.eStateStopped: |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 13 | print >>result, "process must be stopped, state is %s" % lldb.SBDebugger.StateAsCString( |
| 14 | state) |
| 15 | return |
Greg Clayton | 296f166 | 2016-06-28 00:06:35 +0000 | [diff] [blame] | 16 | frame = exe_ctx.GetFrame() |
Greg Clayton | fe9d1ee | 2016-06-23 19:54:32 +0000 | [diff] [blame] | 17 | if not frame: |
| 18 | print >>result, "invalid frame" |
| 19 | return |
| 20 | # Parse command line args |
| 21 | command_args = shlex.split(command) |
| 22 | # TODO: add support for using arguments that are passed to this command... |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 23 | |
Greg Clayton | fe9d1ee | 2016-06-23 19:54:32 +0000 | [diff] [blame] | 24 | # Make a dictionary of variable name to "SBBlock and SBValue" |
Greg Clayton | 296f166 | 2016-06-28 00:06:35 +0000 | [diff] [blame] | 25 | shadow_dict = {} |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 26 | |
Greg Clayton | 296f166 | 2016-06-28 00:06:35 +0000 | [diff] [blame] | 27 | num_shadowed_variables = 0 |
Greg Clayton | fe9d1ee | 2016-06-23 19:54:32 +0000 | [diff] [blame] | 28 | # Get the deepest most block from the current frame |
| 29 | block = frame.GetBlock() |
| 30 | # Iterate through the block and all of its parents |
| 31 | while block.IsValid(): |
| 32 | # Get block variables from the current block only |
| 33 | block_vars = block.GetVariables(frame, True, True, True, 0) |
| 34 | # Iterate through all variables in the current block |
| 35 | for block_var in block_vars: |
Greg Clayton | fe9d1ee | 2016-06-23 19:54:32 +0000 | [diff] [blame] | 36 | # Since we can have multiple shadowed variables, we our variable |
| 37 | # name dictionary to have an array or "block + variable" pairs so |
| 38 | # We can correctly print out all shadowed variables and whow which |
| 39 | # blocks they come from |
Greg Clayton | 296f166 | 2016-06-28 00:06:35 +0000 | [diff] [blame] | 40 | block_var_name = block_var.GetName() |
| 41 | if block_var_name in shadow_dict: |
| 42 | shadow_dict[block_var_name].append(block_var) |
Greg Clayton | fe9d1ee | 2016-06-23 19:54:32 +0000 | [diff] [blame] | 43 | else: |
Greg Clayton | 296f166 | 2016-06-28 00:06:35 +0000 | [diff] [blame] | 44 | shadow_dict[block_var_name] = [block_var] |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 45 | # Get the parent block and continue |
Greg Clayton | fe9d1ee | 2016-06-23 19:54:32 +0000 | [diff] [blame] | 46 | block = block.GetParent() |
Greg Clayton | 296f166 | 2016-06-28 00:06:35 +0000 | [diff] [blame] | 47 | |
| 48 | num_shadowed_variables = 0 |
| 49 | if shadow_dict: |
| 50 | for name in shadow_dict.keys(): |
| 51 | shadow_vars = shadow_dict[name] |
| 52 | if len(shadow_vars) > 1: |
| 53 | print '"%s" is shadowed by the following declarations:' % (name) |
| 54 | num_shadowed_variables += 1 |
| 55 | for shadow_var in shadow_vars: |
| 56 | print >>result, str(shadow_var.GetDeclaration()) |
| 57 | if num_shadowed_variables == 0: |
| 58 | print >>result, 'no variables are shadowed' |