diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp new file mode 100644 index 0000000..05fd53b --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectArgs.cpp @@ -0,0 +1,272 @@ +//===-- CommandObjectArgs.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-python.h" + +#include "CommandObjectArgs.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Args.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/ClangExpression.h" +#include "lldb/Expression/ClangExpressionVariable.h" +#include "lldb/Expression/ClangFunction.h" +#include "lldb/Host/Host.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/StackFrame.h" + +using namespace lldb; +using namespace lldb_private; + +// This command is a toy. I'm just using it to have a way to construct the arguments to +// calling functions. +// + +CommandObjectArgs::CommandOptions::CommandOptions (CommandInterpreter &interpreter) : + Options(interpreter) +{ + // Keep only one place to reset the values to their defaults + OptionParsingStarting(); +} + + +CommandObjectArgs::CommandOptions::~CommandOptions () +{ +} + +Error +CommandObjectArgs::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) +{ + Error error; + + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) + { + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); + break; + } + + return error; +} + +void +CommandObjectArgs::CommandOptions::OptionParsingStarting () +{ +} + +const OptionDefinition* +CommandObjectArgs::CommandOptions::GetDefinitions () +{ + return g_option_table; +} + +CommandObjectArgs::CommandObjectArgs (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "args", + "When stopped at the start of a function, reads function arguments of type (u?)int(8|16|32|64)_t, (void|char)*", + "args"), + m_options (interpreter) +{ +} + +CommandObjectArgs::~CommandObjectArgs () +{ +} + +Options * +CommandObjectArgs::GetOptions () +{ + return &m_options; +} + +bool +CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) +{ + ConstString target_triple; + + + Process *process = m_exe_ctx.GetProcessPtr(); + if (!process) + { + result.AppendError ("Args found no process."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + const ABI *abi = process->GetABI().get(); + if (!abi) + { + result.AppendError ("The current process has no ABI."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + const size_t num_args = args.GetArgumentCount (); + size_t arg_index; + + if (!num_args) + { + result.AppendError ("args requires at least one argument"); + result.SetStatus (eReturnStatusFailed); + return false; + } + + Thread *thread = m_exe_ctx.GetThreadPtr(); + + if (!thread) + { + result.AppendError ("args found no thread."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame (); + if (!thread_cur_frame) + { + result.AppendError ("The current thread has no current frame."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + ModuleSP thread_module_sp (thread_cur_frame->GetFrameCodeAddress ().GetModule()); + if (!thread_module_sp) + { + result.AppendError ("The PC has no associated module."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + ClangASTContext &ast_context = thread_module_sp->GetClangASTContext(); + + ValueList value_list; + + for (arg_index = 0; arg_index < num_args; ++arg_index) + { + const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index); + Value value; + value.SetValueType(Value::eValueTypeScalar); + ClangASTType clang_type; + + char *int_pos; + if ((int_pos = strstr (const_cast<char*>(arg_type_cstr), "int"))) + { + Encoding encoding = eEncodingSint; + + int width = 0; + + if (int_pos > arg_type_cstr + 1) + { + result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus (eReturnStatusFailed); + return false; + } + if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u') + { + result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus (eReturnStatusFailed); + return false; + } + if (arg_type_cstr[0] == 'u') + { + encoding = eEncodingUint; + } + + char *width_pos = int_pos + 3; + + if (!strcmp (width_pos, "8_t")) + width = 8; + else if (!strcmp (width_pos, "16_t")) + width = 16; + else if (!strcmp (width_pos, "32_t")) + width = 32; + else if (!strcmp (width_pos, "64_t")) + width = 64; + else + { + result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus (eReturnStatusFailed); + return false; + } + + clang_type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width); + + if (!clang_type.IsValid()) + { + result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n", + arg_type_cstr, + (encoding == eEncodingSint ? "signed" : "unsigned"), + width); + + result.SetStatus (eReturnStatusFailed); + return false; + } + } + else if (strchr (arg_type_cstr, '*')) + { + if (!strcmp (arg_type_cstr, "void*")) + clang_type = ast_context.GetBasicType(eBasicTypeVoid).GetPointerType(); + else if (!strcmp (arg_type_cstr, "char*")) + clang_type = ast_context.GetCStringType (false); + else + { + result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + else + { + result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); + result.SetStatus (eReturnStatusFailed); + return false; + } + + value.SetClangType (clang_type); + value_list.PushValue(value); + } + + if (!abi->GetArgumentValues (*thread, value_list)) + { + result.AppendError ("Couldn't get argument values"); + result.SetStatus (eReturnStatusFailed); + return false; + } + + result.GetOutputStream ().Printf("Arguments : \n"); + + for (arg_index = 0; arg_index < num_args; ++arg_index) + { + result.GetOutputStream ().Printf ("%zu (%s): ", arg_index, args.GetArgumentAtIndex (arg_index)); + value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ()); + result.GetOutputStream ().Printf("\n"); + } + + return result.Succeeded(); +} + +OptionDefinition +CommandObjectArgs::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."}, + { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } +}; + |