#!/usr/bin/python

#----------------------------------------------------------------------
# For the shells csh, tcsh:
#   ( setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python ; ./globals.py <path> [<path> ...])
#
# For the shells sh, bash:
#   PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python ./globals.py <path> [<path> ...]
#----------------------------------------------------------------------
from __future__ import print_function

import lldb
import optparse
import os
import shlex
import sys


def get_globals(raw_path, options):
    error = lldb.SBError()
    # Resolve the path if needed
    path = os.path.expanduser(raw_path)
    # Create a target using path + options
    target = lldb.debugger.CreateTarget(
        path, options.arch, options.platform, False, error)
    if target:
        # Get the executable module
        module = target.module[target.executable.basename]
        if module:
            # Keep track of which variables we have already looked up
            global_names = list()
            # Iterate through all symbols in the symbol table and watch for any
            # DATA symbols
            for symbol in module.symbols:
                if symbol.type == lldb.eSymbolTypeData:
                    # The symbol is a DATA symbol, lets try and find all global variables
                    # that match this name and print them
                    global_name = symbol.name
                    # Make sure we don't lookup the same variable twice
                    if global_name not in global_names:
                        global_names.append(global_name)
                        # Find all global variables by name
                        global_variable_list = module.FindGlobalVariables(
                            target, global_name, lldb.UINT32_MAX)
                        if global_variable_list:
                            # Print results for anything that matched
                            for global_variable in global_variable_list:
                                # returns the global variable name as a string
                                print('name = %s' % global_variable.name)
                                # Returns the variable value as a string
                                print('value = %s' % global_variable.value)
                                print('type = %s' % global_variable.type)    # Returns an lldb.SBType object
                                # Returns an lldb.SBAddress (section offset
                                # address) for this global
                                print('addr = %s' % global_variable.addr)
                                # Returns the file virtual address for this
                                # global
                                print('file_addr = 0x%x' % global_variable.addr.file_addr)
                                # returns the global variable value as a string
                                print('location = %s' % global_variable.location)
                                # Returns the size in bytes of this global
                                # variable
                                print('size = %s' % global_variable.size)
                                print()


def globals(command_args):
    '''Extract all globals from any arguments which must be paths to object files.'''
    usage = "usage: %prog [options] <PATH> [PATH ...]"
    description = '''This command will find all globals in the specified object file and return an list() of lldb.SBValue objects (which might be empty).'''
    parser = optparse.OptionParser(
        description=description,
        prog='globals',
        usage=usage)
    parser.add_option(
        '-v',
        '--verbose',
        action='store_true',
        dest='verbose',
        help='display verbose debug info',
        default=False)
    parser.add_option(
        '-a',
        '--arch',
        type='string',
        metavar='arch',
        dest='arch',
        help='Specify an architecture (or triple) to use when extracting from a file.')
    parser.add_option(
        '-p',
        '--platform',
        type='string',
        metavar='platform',
        dest='platform',
        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".')
    try:
        (options, args) = parser.parse_args(command_args)
    except:
        return

    for path in args:
        get_globals(path, options)

if __name__ == '__main__':
    lldb.debugger = lldb.SBDebugger.Create()
    globals(sys.argv[1:])
