forked from OSchip/llvm-project
Added some new example code that can grab all functions from any executable, and it will print out the function name, range, return type and argument types.
This example shows someone could iterate over all functions and do something intelligent with them, like create function signatures. Then two different builds could be compared to verify the API hasn't changed. llvm-svn: 183923
This commit is contained in:
parent
dd6b1d5273
commit
07a1d37b88
|
@ -0,0 +1,14 @@
|
|||
LEVEL = ../../test/make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
MY_OS = $(shell uname -s)
|
||||
CXXFLAGS += -std=gnu++11 -stdlib=libc++
|
||||
ifeq "$(MY_OS)" "Darwin"
|
||||
LD_EXTRAS ?= -framework LLDB -Wl,-rpath,/Applications/Xcode.app/Contents/SharedFrameworks
|
||||
FRAMEWORK_INCLUDES=-F/Applications/Xcode.app/Contents/SharedFrameworks
|
||||
else
|
||||
LD_EXTRAS ?= $(LLDB_BUILD_DIR)/_lldb.so
|
||||
endif
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,169 @@
|
|||
//===-- 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 <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <LLDB/LLDB.h>
|
||||
|
||||
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();
|
||||
}
|
||||
};
|
||||
int
|
||||
main (int argc, char const *argv[])
|
||||
{
|
||||
// Use a sentry object to properly initialize/terminate LLDB.
|
||||
LLDBSentry sentry;
|
||||
|
||||
if (argc < 2)
|
||||
exit (1);
|
||||
|
||||
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)
|
||||
{
|
||||
// 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());
|
||||
|
||||
if (debugger.IsValid())
|
||||
{
|
||||
// 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();
|
||||
|
||||
printf ("\nfunction name: %s\n", function.GetName());
|
||||
printf ("function range:[0x%llx - 0x%llx)\n", lo_pc, hi_pc);
|
||||
SBType function_type = function.GetType();
|
||||
SBType return_type = function_type.GetFunctionReturnType();
|
||||
if (return_type.IsValid())
|
||||
{
|
||||
printf ("return type: %s\n", return_type.GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("return type: <NONE>\n");
|
||||
}
|
||||
|
||||
|
||||
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_arg_type = function_args.GetTypeAtIndex(function_arg_idx);
|
||||
if (function_arg_type.IsValid())
|
||||
{
|
||||
printf ("arg[%u] type: %s\n", function_arg_idx, function_arg_type.GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("arg[%u] type: <invalid>\n", function_arg_idx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: %s\n", error.GetCString());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue