1#!/usr/bin/python
2
3#----------------------------------------------------------------------
4# For the shells csh, tcsh:
5#   ( setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python ; ./globals.py <path> [<path> ...])
6#
7# For the shells sh, bash:
8#   PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python ./globals.py <path> [<path> ...]
9#----------------------------------------------------------------------
10from __future__ import print_function
11
12import lldb
13import commands
14import optparse
15import os
16import shlex
17import sys
18
19
20def get_globals(raw_path, options):
21    error = lldb.SBError()
22    # Resolve the path if needed
23    path = os.path.expanduser(raw_path)
24    # Create a target using path + options
25    target = lldb.debugger.CreateTarget(
26        path, options.arch, options.platform, False, error)
27    if target:
28        # Get the executable module
29        module = target.module[target.executable.basename]
30        if module:
31            # Keep track of which variables we have already looked up
32            global_names = list()
33            # Iterate through all symbols in the symbol table and watch for any
34            # DATA symbols
35            for symbol in module.symbols:
36                if symbol.type == lldb.eSymbolTypeData:
37                    # The symbol is a DATA symbol, lets try and find all global variables
38                    # that match this name and print them
39                    global_name = symbol.name
40                    # Make sure we don't lookup the same variable twice
41                    if global_name not in global_names:
42                        global_names.append(global_name)
43                        # Find all global variables by name
44                        global_variable_list = module.FindGlobalVariables(
45                            target, global_name, lldb.UINT32_MAX)
46                        if global_variable_list:
47                            # Print results for anything that matched
48                            for global_variable in global_variable_list:
49                                # returns the global variable name as a string
50                                print('name = %s' % global_variable.name)
51                                # Returns the variable value as a string
52                                print('value = %s' % global_variable.value)
53                                print('type = %s' % global_variable.type)    # Returns an lldb.SBType object
54                                # Returns an lldb.SBAddress (section offset
55                                # address) for this global
56                                print('addr = %s' % global_variable.addr)
57                                # Returns the file virtual address for this
58                                # global
59                                print('file_addr = 0x%x' % global_variable.addr.file_addr)
60                                # returns the global variable value as a string
61                                print('location = %s' % global_variable.location)
62                                # Returns the size in bytes of this global
63                                # variable
64                                print('size = %s' % global_variable.size)
65                                print()
66
67
68def globals(command_args):
69    '''Extract all globals from any arguments which must be paths to object files.'''
70    usage = "usage: %prog [options] <PATH> [PATH ...]"
71    description = '''This command will find all globals in the specified object file and return an list() of lldb.SBValue objects (which might be empty).'''
72    parser = optparse.OptionParser(
73        description=description,
74        prog='globals',
75        usage=usage)
76    parser.add_option(
77        '-v',
78        '--verbose',
79        action='store_true',
80        dest='verbose',
81        help='display verbose debug info',
82        default=False)
83    parser.add_option(
84        '-a',
85        '--arch',
86        type='string',
87        metavar='arch',
88        dest='arch',
89        help='Specify an architecture (or triple) to use when extracting from a file.')
90    parser.add_option(
91        '-p',
92        '--platform',
93        type='string',
94        metavar='platform',
95        dest='platform',
96        help='Specify the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
97    try:
98        (options, args) = parser.parse_args(command_args)
99    except:
100        return
101
102    for path in args:
103        get_globals(path, options)
104
105if __name__ == '__main__':
106    lldb.debugger = lldb.SBDebugger.Create()
107    globals(sys.argv[1:])
108