diff options
Diffstat (limited to 'examples/functions/main.cpp')
| -rw-r--r-- | examples/functions/main.cpp | 364 | 
1 files changed, 364 insertions, 0 deletions
| diff --git a/examples/functions/main.cpp b/examples/functions/main.cpp new file mode 100644 index 000000000000..4381098e3305 --- /dev/null +++ b/examples/functions/main.cpp @@ -0,0 +1,364 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <getopt.h> +#include <stdint.h> +#include <stdlib.h> + +#if defined(__APPLE__) +#include <LLDB/LLDB.h> +#else +#include "LLDB/SBBlock.h" +#include "LLDB/SBCompileUnit.h" +#include "LLDB/SBDebugger.h" +#include "LLDB/SBFunction.h" +#include "LLDB/SBModule.h" +#include "LLDB/SBStream.h" +#include "LLDB/SBSymbol.h" +#include "LLDB/SBTarget.h" +#include "LLDB/SBThread.h" +#include "LLDB/SBProcess.h" +#endif + +#include <string> + +using namespace lldb; + +//---------------------------------------------------------------------- +// This quick sample code shows how to create a debugger instance and +// create an executable target without adding dependent shared +// libraries. It will then set a regular expression breakpoint to get +// breakpoint locations for all functions in the module, and use the  +// locations to extract the symbol context for each location. Then it  +// dumps all // information about the function: its name, file address  +// range, the return type (if any), and all argument types. +// +// To build the program, type (while in this directory): +// +//    $ make +// +// then to run this on MacOSX, specify the path to your LLDB.framework +// library using the DYLD_FRAMEWORK_PATH option and run the executable +// +//    $ DYLD_FRAMEWORK_PATH=/Volumes/data/lldb/tot/build/Debug ./a.out executable_path1 [executable_path2 ...]  +//---------------------------------------------------------------------- +class LLDBSentry +{ +public: +    LLDBSentry() { +        // Initialize LLDB +        SBDebugger::Initialize(); +    } +    ~LLDBSentry() { +        // Terminate LLDB +        SBDebugger::Terminate(); +    } +}; + +static struct option g_long_options[] =  +{ +	{ "arch",		required_argument,	NULL, 'a' }, +	{ "canonical",  no_argument,	    NULL, 'c' }, +	{ "extern",     no_argument,	    NULL, 'x' }, +    { "help",       no_argument,        NULL, 'h' }, +	{ "platform",   required_argument,	NULL, 'p' }, +    { "verbose",    no_argument,        NULL, 'v' }, +	{ NULL,			0,					NULL,  0  } +}; + +#define PROGRAM_NAME "lldb-functions" +void +usage () +{ +    puts ( +    "NAME\n" +    "    " PROGRAM_NAME " -- extract all function signatures from one or more binaries.\n" +    "\n" +    "SYNOPSIS\n" +    "    " PROGRAM_NAME " [[--arch=<ARCH>] [--platform=<PLATFORM>] [--verbose] [--help] [--canonical] --] <PATH> [<PATH>....]\n" +    "\n" +    "DESCRIPTION\n" +    "    Loads the executable pointed to by <PATH> and dumps complete signatures for all functions that have debug information.\n" +    "\n" +    "EXAMPLE\n" +    "   " PROGRAM_NAME " --arch=x86_64 /usr/lib/dyld\n" +    ); +    exit(0); +} +int +main (int argc, char const *argv[]) +{ +    // Use a sentry object to properly initialize/terminate LLDB. +    LLDBSentry sentry; +     +    SBDebugger debugger (SBDebugger::Create()); +     +    // Create a debugger instance so we can create a target +    if (!debugger.IsValid()) +        fprintf (stderr, "error: failed to create a debugger object\n"); +     +    bool show_usage = false; +    bool verbose = false; +    bool canonical = false; +    bool external_only = false; +    const char *arch = NULL; +    const char *platform = NULL; +    std::string short_options("h?"); +    for (const struct option *opt = g_long_options; opt->name; ++opt) +    { +        if (isprint(opt->val)) +        { +            short_options.append(1, (char)opt->val); +            switch (opt->has_arg) +            { +            case no_argument: +                break; +            case required_argument: +                short_options.append(1, ':');  +                break; +            case optional_argument: +                short_options.append(2, ':');  +                break; +            }    +        }         +    } +#ifdef __GLIBC__ +    optind = 0; +#else +    optreset = 1; +    optind = 1; +#endif +    char ch; +	while ((ch = getopt_long_only(argc, (char * const *)argv, short_options.c_str(), g_long_options, 0)) != -1) +	{ +		switch (ch)  +		{ +        case 0: +            break; + +		case 'a': +		    if (arch != NULL) +		    { +                fprintf (stderr, "error: the --arch option can only be specified once\n"); +                exit(1); +		    } +            arch = optarg; +			break; + +        case 'c': +            canonical = true; +            break; + +        case 'x': +            external_only = true; +            break; +     +        case 'p': +            platform = optarg; +            break;             +         +        case 'v': +            verbose = true; +            break; + +		case 'h': +		case '?': +		default: +			show_usage = true; +			break; +		} +	} +	argc -= optind; +	argv += optind; +     +    const bool add_dependent_libs = false; +    SBError error; +    for (int arg_idx = 0; arg_idx < argc; ++arg_idx) +    { +        // The first argument is the file path we want to look something up in +        const char *exe_file_path = argv[arg_idx]; +         +        // Create a target using the executable. +        SBTarget target = debugger.CreateTarget (exe_file_path, +                                                 arch, +                                                 platform, +                                                 add_dependent_libs, +                                                 error); +         +        if (error.Success()) +        { +            if (target.IsValid()) +            { +                SBFileSpec exe_file_spec (exe_file_path, true); +                SBModule module (target.FindModule (exe_file_spec)); +                SBFileSpecList comp_unit_list; + +                if (module.IsValid()) +                { +                    char command[1024]; +                    lldb::SBCommandReturnObject command_result; +                    snprintf (command, sizeof(command), "add-dsym --uuid %s", module.GetUUIDString()); +                    debugger.GetCommandInterpreter().HandleCommand (command, command_result); +                    if (!command_result.Succeeded()) +                    { +                        fprintf (stderr, "error: couldn't locate debug symbols for '%s'\n", exe_file_path); +                        exit(1); +                    } + +                    SBFileSpecList module_list; +                    module_list.Append(exe_file_spec); +                    SBBreakpoint bp = target.BreakpointCreateByRegex (".", module_list, comp_unit_list); +                     +                    const size_t num_locations = bp.GetNumLocations(); +                    for (uint32_t bp_loc_idx=0; bp_loc_idx<num_locations; ++bp_loc_idx) +                    { +                        SBBreakpointLocation bp_loc = bp.GetLocationAtIndex(bp_loc_idx); +                        SBSymbolContext sc (bp_loc.GetAddress().GetSymbolContext(eSymbolContextEverything)); +                        if (sc.IsValid()) +                        { +                            if (sc.GetBlock().GetContainingInlinedBlock().IsValid()) +                            { +                                // Skip inlined functions +                                continue; +                            } +                            SBFunction function (sc.GetFunction()); +                            if (function.IsValid()) +                            { +                                addr_t lo_pc = function.GetStartAddress().GetFileAddress(); +                                if (lo_pc == LLDB_INVALID_ADDRESS) +                                { +                                    // Skip functions that don't have concrete instances in the binary +                                    continue; +                                } +                                addr_t hi_pc = function.GetEndAddress().GetFileAddress(); +                                const char *func_demangled_name = function.GetName(); +                                const char *func_mangled_name = function.GetMangledName(); +                                 +                                bool dump = true; +                                const bool is_objc_method = ((func_demangled_name[0] == '-') || (func_demangled_name[0] == '+')) && (func_demangled_name[1] == '['); +                                if (external_only) +                                { +                                    // Dump all objective C methods, or external symbols +                                    dump = is_objc_method; +                                    if (!dump) +                                        dump = sc.GetSymbol().IsExternal(); +                                } + +                                if (dump) +                                { +                                    if (verbose) +                                    { +                                        printf ("\n   name: %s\n", func_demangled_name); +                                        if (func_mangled_name) +                                            printf ("mangled: %s\n", func_mangled_name); +                                        printf ("  range: [0x%16.16llx - 0x%16.16llx)\n   type: ", lo_pc, hi_pc); +                                    } +                                    else +                                    { +                                        printf ("[0x%16.16llx - 0x%16.16llx) ", lo_pc, hi_pc); +                                    } +                                    SBType function_type = function.GetType(); +                                    SBType return_type = function_type.GetFunctionReturnType(); +                                 +                                    if (canonical) +                                        return_type = return_type.GetCanonicalType(); + +                                    if (func_mangled_name &&  +                                        func_mangled_name[0] == '_' && +                                        func_mangled_name[1] == 'Z') +                                    { +                                        printf ("%s %s\n", return_type.GetName(), func_demangled_name); +                                    } +                                    else  +                                    { +                                        SBTypeList function_args = function_type.GetFunctionArgumentTypes(); +                                        const size_t num_function_args = function_args.GetSize(); +                                     +                                        if (is_objc_method) +                                        { +                                            const char *class_name_start = func_demangled_name + 2; +                                         +                                            if (num_function_args == 0) +                                            { +                                                printf("%c(%s)[%s\n", func_demangled_name[0], return_type.GetName(), class_name_start); +                                            } +                                            else +                                            { +                                                const char *class_name_end = strchr(class_name_start,' '); +                                                const int class_name_len = class_name_end - class_name_start; +                                                printf ("%c(%s)[%*.*s", func_demangled_name[0], return_type.GetName(), class_name_len, class_name_len, class_name_start); +                                         +                                                const char *selector_pos = class_name_end + 1; +                                                for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args; ++function_arg_idx) +                                                { +                                                    const char *selector_end = strchr(selector_pos, ':') + 1; +                                                    const int selector_len = selector_end - selector_pos;  +                                                    SBType function_arg_type = function_args.GetTypeAtIndex(function_arg_idx); + +                                                    if (canonical) +                                                        function_arg_type = function_arg_type.GetCanonicalType(); + +                                                    printf (" %*.*s", selector_len, selector_len, selector_pos); +                                                    if (function_arg_type.IsValid()) +                                                    { +                                                        printf ("(%s)", function_arg_type.GetName()); +                                                    } +                                                    else +                                                    { +                                                        printf ("(?)"); +                                                    } +                                                    selector_pos = selector_end; +                                                } +                                                printf ("]\n"); +                                            } +                                        } +                                        else +                                        { +                                            printf ("%s ", return_type.GetName()); +                                            if (strchr (func_demangled_name, '(')) +                                                printf ("(*)("); +                                            else +                                                printf ("%s(", func_demangled_name); +                                 +                                            for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args; ++function_arg_idx) +                                            { +                                                SBType function_arg_type = function_args.GetTypeAtIndex(function_arg_idx); + +                                                if (canonical) +                                                    function_arg_type = function_arg_type.GetCanonicalType(); +                                             +                                                if (function_arg_type.IsValid()) +                                                { +                                                    printf ("%s%s", function_arg_idx > 0 ? ", " : "", function_arg_type.GetName()); +                                                } +                                                else +                                                { +                                                    printf ("%s???", function_arg_idx > 0 ? ", " : ""); +                                                } +                                            } +                                            printf (")\n");                             +                                        }     +                                    } +                                } +                            } +                        } +                    } +                } +            } +        } +        else +        { +            fprintf (stderr, "error: %s\n", error.GetCString()); +            exit(1); +        } +    } +     +    return 0; +} + | 
