summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lldb/examples/functions/main.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 14:33:06 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 14:33:06 +0000
commit061da546b983eb767bad15e67af1174fb0bcf31c (patch)
tree83c78b820819d70aa40c36d90447978b300078c5 /gnu/llvm/lldb/examples/functions/main.cpp
parentImport LLVM 10.0.0 release including clang, lld and lldb. (diff)
downloadwireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.tar.xz
wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.zip
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom tested by plenty
Diffstat (limited to 'gnu/llvm/lldb/examples/functions/main.cpp')
-rw-r--r--gnu/llvm/lldb/examples/functions/main.cpp343
1 files changed, 343 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/examples/functions/main.cpp b/gnu/llvm/lldb/examples/functions/main.cpp
new file mode 100644
index 00000000000..07fb206f8b1
--- /dev/null
+++ b/gnu/llvm/lldb/examples/functions/main.cpp
@@ -0,0 +1,343 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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/SBProcess.h"
+#include "LLDB/SBStream.h"
+#include "LLDB/SBSymbol.h"
+#include "LLDB/SBTarget.h"
+#include "LLDB/SBThread.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;
+}