diff --git a/lldb/examples/functions/main.cpp b/lldb/examples/functions/main.cpp index 3f27b3993acb..4381098e3305 100644 --- a/lldb/examples/functions/main.cpp +++ b/lldb/examples/functions/main.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include #include #include @@ -25,6 +26,8 @@ #include "LLDB/SBProcess.h" #endif +#include + using namespace lldb; //---------------------------------------------------------------------- @@ -57,123 +60,302 @@ public: 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=] [--platform=] [--verbose] [--help] [--canonical] --] [....]\n" + "\n" + "DESCRIPTION\n" + " Loads the executable pointed to by 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; - if (argc < 2) - exit (1); + 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 char *arch = NULL; // Fill this in with "x86_64" or "i386" as needed - const char *platform = NULL; // Leave NULL for native platform, set to a valid other platform name if required const bool add_dependent_libs = false; SBError error; - for (int arg_idx = 1; arg_idx < argc; ++arg_idx) + for (int arg_idx = 0; arg_idx < argc; ++arg_idx) { - // The first argument is the file path we want to look something up in + // The first argument is the file path we want to look something up in const char *exe_file_path = argv[arg_idx]; - // Create a debugger instance so we can create a target - SBDebugger debugger (SBDebugger::Create()); + // Create a target using the executable. + SBTarget target = debugger.CreateTarget (exe_file_path, + arch, + platform, + add_dependent_libs, + error); - if (debugger.IsValid()) + if (error.Success()) { - // 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()) { - 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()) { - 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()) { - 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); - } + 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\n"); + printf ("[0x%16.16llx - 0x%16.16llx) ", lo_pc, hi_pc); } - - - SBTypeList function_args = function_type.GetFunctionArgumentTypes(); - const size_t num_function_args = function_args.GetSize(); - for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args; ++function_arg_idx) + 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') { - SBType function_arg_type = function_args.GetTypeAtIndex(function_arg_idx); - if (function_arg_type.IsValid()) + 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) { - printf ("arg[%u] type: %s\n", function_arg_idx, function_arg_type.GetName()); + 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 ("arg[%u] type: \n", function_arg_idx); - } + 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); - } + } + else + { + fprintf (stderr, "error: %s\n", error.GetCString()); + exit(1); } }