CommandObjectArgs.cpp revision 254729
169800Stomsoft//===-- CommandObjectArgs.cpp -----------------------------------*- C++ -*-===//
269800Stomsoft//
369800Stomsoft//                     The LLVM Compiler Infrastructure
469800Stomsoft//
5114067Sschweikh// This file is distributed under the University of Illinois Open Source
669800Stomsoft// License. See LICENSE.TXT for details.
769800Stomsoft//
8114067Sschweikh//===----------------------------------------------------------------------===//
969800Stomsoft
1069800Stomsoft#include "lldb/lldb-python.h"
1169800Stomsoft
1269800Stomsoft#include "CommandObjectArgs.h"
1369800Stomsoft
1469800Stomsoft// C Includes
1569800Stomsoft// C++ Includes
1669800Stomsoft// Other libraries and framework includes
1769800Stomsoft// Project includes
1869800Stomsoft#include "lldb/Interpreter/Args.h"
1969800Stomsoft#include "lldb/Core/Debugger.h"
2069800Stomsoft#include "lldb/Core/Module.h"
2169800Stomsoft#include "lldb/Core/Value.h"
2269800Stomsoft#include "lldb/Expression/ClangExpression.h"
2369800Stomsoft#include "lldb/Expression/ClangExpressionVariable.h"
2469800Stomsoft#include "lldb/Expression/ClangFunction.h"
25114067Sschweikh#include "lldb/Host/Host.h"
2669800Stomsoft#include "lldb/Interpreter/CommandInterpreter.h"
2769800Stomsoft#include "lldb/Interpreter/CommandReturnObject.h"
2869800Stomsoft#include "lldb/Symbol/ObjectFile.h"
2969800Stomsoft#include "lldb/Symbol/Variable.h"
3069800Stomsoft#include "lldb/Target/Process.h"
3169800Stomsoft#include "lldb/Target/Target.h"
3269800Stomsoft#include "lldb/Target/Thread.h"
3369800Stomsoft#include "lldb/Target/StackFrame.h"
3469800Stomsoft
3569800Stomsoftusing namespace lldb;
3669800Stomsoftusing namespace lldb_private;
3769800Stomsoft
3869926Stomsoft// This command is a toy.  I'm just using it to have a way to construct the arguments to
3969800Stomsoft// calling functions.
4069800Stomsoft//
4169800Stomsoft
4269800StomsoftCommandObjectArgs::CommandOptions::CommandOptions (CommandInterpreter &interpreter) :
4369800Stomsoft    Options(interpreter)
4469800Stomsoft{
4569800Stomsoft    // Keep only one place to reset the values to their defaults
4669800Stomsoft    OptionParsingStarting();
4769800Stomsoft}
4869800Stomsoft
49140351Scharnier
50140351ScharnierCommandObjectArgs::CommandOptions::~CommandOptions ()
5169800Stomsoft{
5269800Stomsoft}
5369800Stomsoft
5469800StomsoftError
5569800StomsoftCommandObjectArgs::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
5669800Stomsoft{
57114936Sgrog    Error error;
5869800Stomsoft
5969800Stomsoft    const int short_option = m_getopt_table[option_idx].val;
6069800Stomsoft
6169800Stomsoft    switch (short_option)
6269800Stomsoft    {
6369800Stomsoft        default:
64103949Smike            error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
6569800Stomsoft            break;
66127798Sle    }
6769800Stomsoft
68127821Sbde    return error;
6969800Stomsoft}
7069800Stomsoft
7169800Stomsoftvoid
7269800StomsoftCommandObjectArgs::CommandOptions::OptionParsingStarting ()
7369800Stomsoft{
7469800Stomsoft}
7569800Stomsoft
7669800Stomsoftconst OptionDefinition*
7769800StomsoftCommandObjectArgs::CommandOptions::GetDefinitions ()
7869800Stomsoft{
7969800Stomsoft    return g_option_table;
8069800Stomsoft}
8169800Stomsoft
8298542SmckusickCommandObjectArgs::CommandObjectArgs (CommandInterpreter &interpreter) :
8369800Stomsoft    CommandObjectParsed (interpreter,
8469800Stomsoft                         "args",
8569800Stomsoft                         "When stopped at the start of a function, reads function arguments of type (u?)int(8|16|32|64)_t, (void|char)*",
8669800Stomsoft                         "args"),
8798542Smckusick    m_options (interpreter)
8898542Smckusick{
8998542Smckusick}
9098542Smckusick
9198542SmckusickCommandObjectArgs::~CommandObjectArgs ()
9298542Smckusick{
9369800Stomsoft}
9469800Stomsoft
9569800StomsoftOptions *
9669800StomsoftCommandObjectArgs::GetOptions ()
9769800Stomsoft{
9869800Stomsoft    return &m_options;
9969800Stomsoft}
10098542Smckusick
10169800Stomsoftbool
10298542SmckusickCommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
10369800Stomsoft{
10498542Smckusick    ConstString target_triple;
10598542Smckusick
10698542Smckusick
10769800Stomsoft    Process *process = m_exe_ctx.GetProcessPtr();
10898542Smckusick    if (!process)
10998542Smckusick    {
110127798Sle        result.AppendError ("Args found no process.");
111132832Sle        result.SetStatus (eReturnStatusFailed);
112132832Sle        return false;
113132832Sle    }
114132832Sle
115132832Sle    const ABI *abi = process->GetABI().get();
116132832Sle    if (!abi)
11798542Smckusick    {
11898542Smckusick        result.AppendError ("The current process has no ABI.");
119127798Sle        result.SetStatus (eReturnStatusFailed);
120114936Sgrog        return false;
12169800Stomsoft    }
12269800Stomsoft
123114067Sschweikh    const size_t num_args = args.GetArgumentCount ();
12469800Stomsoft    size_t arg_index;
12569800Stomsoft
12669800Stomsoft    if (!num_args)
12769800Stomsoft    {
12898542Smckusick        result.AppendError ("args requires at least one argument");
12998542Smckusick        result.SetStatus (eReturnStatusFailed);
13069800Stomsoft        return false;
13169800Stomsoft    }
13277885Stomsoft
13369800Stomsoft    Thread *thread = m_exe_ctx.GetThreadPtr();
13469800Stomsoft
13569800Stomsoft    if (!thread)
13669800Stomsoft    {
13777885Stomsoft        result.AppendError ("args found no thread.");
13898542Smckusick        result.SetStatus (eReturnStatusFailed);
13998542Smckusick        return false;
14098542Smckusick    }
14169800Stomsoft
14269926Stomsoft    lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame ();
14369800Stomsoft    if (!thread_cur_frame)
14469800Stomsoft    {
14569800Stomsoft        result.AppendError ("The current thread has no current frame.");
14677885Stomsoft        result.SetStatus (eReturnStatusFailed);
14777885Stomsoft        return false;
14877885Stomsoft    }
14969800Stomsoft
15077885Stomsoft    ModuleSP thread_module_sp (thread_cur_frame->GetFrameCodeAddress ().GetModule());
15198542Smckusick    if (!thread_module_sp)
15298542Smckusick    {
15398542Smckusick        result.AppendError ("The PC has no associated module.");
15498542Smckusick        result.SetStatus (eReturnStatusFailed);
15569800Stomsoft        return false;
15677885Stomsoft    }
15798542Smckusick
15898542Smckusick    ClangASTContext &ast_context = thread_module_sp->GetClangASTContext();
159114936Sgrog
16069800Stomsoft    ValueList value_list;
16169800Stomsoft
16269800Stomsoft    for (arg_index = 0; arg_index < num_args; ++arg_index)
163114067Sschweikh    {
164114067Sschweikh        const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index);
165114067Sschweikh        Value value;
16669800Stomsoft        value.SetValueType(Value::eValueTypeScalar);
167114067Sschweikh        ClangASTType clang_type;
168114067Sschweikh
169114067Sschweikh        char *int_pos;
17069800Stomsoft        if ((int_pos = strstr (const_cast<char*>(arg_type_cstr), "int")))
17169800Stomsoft        {
17269800Stomsoft            Encoding encoding = eEncodingSint;
17369800Stomsoft
17477885Stomsoft            int width = 0;
17569800Stomsoft
17669800Stomsoft            if (int_pos > arg_type_cstr + 1)
17769800Stomsoft            {
178203770Smckusick                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
179203770Smckusick                result.SetStatus (eReturnStatusFailed);
18069800Stomsoft                return false;
18169800Stomsoft            }
18269800Stomsoft            if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u')
18369800Stomsoft            {
18469800Stomsoft                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
18569800Stomsoft                result.SetStatus (eReturnStatusFailed);
18669800Stomsoft                return false;
18769800Stomsoft            }
18869800Stomsoft            if (arg_type_cstr[0] == 'u')
18969800Stomsoft            {
19069800Stomsoft                encoding = eEncodingUint;
19169800Stomsoft            }
19269800Stomsoft
19369800Stomsoft            char *width_pos = int_pos + 3;
19469800Stomsoft
19569800Stomsoft            if (!strcmp (width_pos, "8_t"))
19669800Stomsoft                width = 8;
19769800Stomsoft            else if (!strcmp (width_pos, "16_t"))
19869800Stomsoft                width = 16;
19969800Stomsoft            else if (!strcmp (width_pos, "32_t"))
20077885Stomsoft                width = 32;
20169926Stomsoft            else if (!strcmp (width_pos, "64_t"))
20269926Stomsoft                width = 64;
20369926Stomsoft            else
20469800Stomsoft            {
20569800Stomsoft                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
20677885Stomsoft                result.SetStatus (eReturnStatusFailed);
20777885Stomsoft                return false;
20869800Stomsoft            }
20969800Stomsoft
21069800Stomsoft            clang_type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
21169800Stomsoft
21269800Stomsoft            if (!clang_type.IsValid())
21369800Stomsoft            {
21469800Stomsoft                result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n",
21569800Stomsoft                                             arg_type_cstr,
21669800Stomsoft                                             (encoding == eEncodingSint ? "signed" : "unsigned"),
21769800Stomsoft                                             width);
21877885Stomsoft
21977885Stomsoft                result.SetStatus (eReturnStatusFailed);
22069926Stomsoft                return false;
22169926Stomsoft            }
22269926Stomsoft        }
22369800Stomsoft        else if (strchr (arg_type_cstr, '*'))
22469800Stomsoft        {
22569800Stomsoft            if (!strcmp (arg_type_cstr, "void*"))
22669800Stomsoft                clang_type = ast_context.GetBasicType(eBasicTypeVoid).GetPointerType();
22769800Stomsoft            else if (!strcmp (arg_type_cstr, "char*"))
22869800Stomsoft                clang_type = ast_context.GetCStringType (false);
22969800Stomsoft            else
23069800Stomsoft            {
23169800Stomsoft                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
23269800Stomsoft                result.SetStatus (eReturnStatusFailed);
23369800Stomsoft                return false;
234102231Strhodes            }
23569800Stomsoft        }
23698542Smckusick        else
237127816Smux        {
23869800Stomsoft            result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
239127816Smux            result.SetStatus (eReturnStatusFailed);
240127816Smux            return false;
24198542Smckusick        }
24298542Smckusick
24398542Smckusick        value.SetClangType (clang_type);
24498542Smckusick        value_list.PushValue(value);
24598542Smckusick    }
24698542Smckusick
24769800Stomsoft    if (!abi->GetArgumentValues (*thread, value_list))
24869800Stomsoft    {
24969800Stomsoft        result.AppendError ("Couldn't get argument values");
25069800Stomsoft        result.SetStatus (eReturnStatusFailed);
25169800Stomsoft        return false;
25269800Stomsoft    }
25369800Stomsoft
25469800Stomsoft    result.GetOutputStream ().Printf("Arguments : \n");
25569800Stomsoft
25669800Stomsoft    for (arg_index = 0; arg_index < num_args; ++arg_index)
25769800Stomsoft    {
25869800Stomsoft        result.GetOutputStream ().Printf ("%zu (%s): ", arg_index, args.GetArgumentAtIndex (arg_index));
25969800Stomsoft        value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ());
26069800Stomsoft        result.GetOutputStream ().Printf("\n");
261174706Sdas    }
262174706Sdas
26369800Stomsoft    return result.Succeeded();
26469800Stomsoft}
26569800Stomsoft
26669800StomsoftOptionDefinition
26769800StomsoftCommandObjectArgs::CommandOptions::g_option_table[] =
26869800Stomsoft{
26969800Stomsoft    { LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
27069800Stomsoft    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
27169800Stomsoft};
27269800Stomsoft
27369800Stomsoft