1//===-- CommandObjectArgs.cpp -----------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/lldb-python.h"
11
12#include "CommandObjectArgs.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Interpreter/Args.h"
19#include "lldb/Core/Debugger.h"
20#include "lldb/Core/Module.h"
21#include "lldb/Core/Value.h"
22#include "lldb/Expression/ClangExpression.h"
23#include "lldb/Expression/ClangExpressionVariable.h"
24#include "lldb/Expression/ClangFunction.h"
25#include "lldb/Host/Host.h"
26#include "lldb/Interpreter/CommandInterpreter.h"
27#include "lldb/Interpreter/CommandReturnObject.h"
28#include "lldb/Symbol/ObjectFile.h"
29#include "lldb/Symbol/Variable.h"
30#include "lldb/Target/Process.h"
31#include "lldb/Target/Target.h"
32#include "lldb/Target/Thread.h"
33#include "lldb/Target/StackFrame.h"
34
35using namespace lldb;
36using namespace lldb_private;
37
38// This command is a toy.  I'm just using it to have a way to construct the arguments to
39// calling functions.
40//
41
42CommandObjectArgs::CommandOptions::CommandOptions (CommandInterpreter &interpreter) :
43    Options(interpreter)
44{
45    // Keep only one place to reset the values to their defaults
46    OptionParsingStarting();
47}
48
49
50CommandObjectArgs::CommandOptions::~CommandOptions ()
51{
52}
53
54Error
55CommandObjectArgs::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
56{
57    Error error;
58
59    const int short_option = m_getopt_table[option_idx].val;
60
61    switch (short_option)
62    {
63        default:
64            error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
65            break;
66    }
67
68    return error;
69}
70
71void
72CommandObjectArgs::CommandOptions::OptionParsingStarting ()
73{
74}
75
76const OptionDefinition*
77CommandObjectArgs::CommandOptions::GetDefinitions ()
78{
79    return g_option_table;
80}
81
82CommandObjectArgs::CommandObjectArgs (CommandInterpreter &interpreter) :
83    CommandObjectParsed (interpreter,
84                         "args",
85                         "When stopped at the start of a function, reads function arguments of type (u?)int(8|16|32|64)_t, (void|char)*",
86                         "args"),
87    m_options (interpreter)
88{
89}
90
91CommandObjectArgs::~CommandObjectArgs ()
92{
93}
94
95Options *
96CommandObjectArgs::GetOptions ()
97{
98    return &m_options;
99}
100
101bool
102CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
103{
104    ConstString target_triple;
105
106
107    Process *process = m_exe_ctx.GetProcessPtr();
108    if (!process)
109    {
110        result.AppendError ("Args found no process.");
111        result.SetStatus (eReturnStatusFailed);
112        return false;
113    }
114
115    const ABI *abi = process->GetABI().get();
116    if (!abi)
117    {
118        result.AppendError ("The current process has no ABI.");
119        result.SetStatus (eReturnStatusFailed);
120        return false;
121    }
122
123    const size_t num_args = args.GetArgumentCount ();
124    size_t arg_index;
125
126    if (!num_args)
127    {
128        result.AppendError ("args requires at least one argument");
129        result.SetStatus (eReturnStatusFailed);
130        return false;
131    }
132
133    Thread *thread = m_exe_ctx.GetThreadPtr();
134
135    if (!thread)
136    {
137        result.AppendError ("args found no thread.");
138        result.SetStatus (eReturnStatusFailed);
139        return false;
140    }
141
142    lldb::StackFrameSP thread_cur_frame = thread->GetSelectedFrame ();
143    if (!thread_cur_frame)
144    {
145        result.AppendError ("The current thread has no current frame.");
146        result.SetStatus (eReturnStatusFailed);
147        return false;
148    }
149
150    ModuleSP thread_module_sp (thread_cur_frame->GetFrameCodeAddress ().GetModule());
151    if (!thread_module_sp)
152    {
153        result.AppendError ("The PC has no associated module.");
154        result.SetStatus (eReturnStatusFailed);
155        return false;
156    }
157
158    ClangASTContext &ast_context = thread_module_sp->GetClangASTContext();
159
160    ValueList value_list;
161
162    for (arg_index = 0; arg_index < num_args; ++arg_index)
163    {
164        const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index);
165        Value value;
166        value.SetValueType(Value::eValueTypeScalar);
167        ClangASTType clang_type;
168
169        char *int_pos;
170        if ((int_pos = strstr (const_cast<char*>(arg_type_cstr), "int")))
171        {
172            Encoding encoding = eEncodingSint;
173
174            int width = 0;
175
176            if (int_pos > arg_type_cstr + 1)
177            {
178                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
179                result.SetStatus (eReturnStatusFailed);
180                return false;
181            }
182            if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u')
183            {
184                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
185                result.SetStatus (eReturnStatusFailed);
186                return false;
187            }
188            if (arg_type_cstr[0] == 'u')
189            {
190                encoding = eEncodingUint;
191            }
192
193            char *width_pos = int_pos + 3;
194
195            if (!strcmp (width_pos, "8_t"))
196                width = 8;
197            else if (!strcmp (width_pos, "16_t"))
198                width = 16;
199            else if (!strcmp (width_pos, "32_t"))
200                width = 32;
201            else if (!strcmp (width_pos, "64_t"))
202                width = 64;
203            else
204            {
205                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
206                result.SetStatus (eReturnStatusFailed);
207                return false;
208            }
209
210            clang_type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
211
212            if (!clang_type.IsValid())
213            {
214                result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n",
215                                             arg_type_cstr,
216                                             (encoding == eEncodingSint ? "signed" : "unsigned"),
217                                             width);
218
219                result.SetStatus (eReturnStatusFailed);
220                return false;
221            }
222        }
223        else if (strchr (arg_type_cstr, '*'))
224        {
225            if (!strcmp (arg_type_cstr, "void*"))
226                clang_type = ast_context.GetBasicType(eBasicTypeVoid).GetPointerType();
227            else if (!strcmp (arg_type_cstr, "char*"))
228                clang_type = ast_context.GetCStringType (false);
229            else
230            {
231                result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
232                result.SetStatus (eReturnStatusFailed);
233                return false;
234            }
235        }
236        else
237        {
238            result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
239            result.SetStatus (eReturnStatusFailed);
240            return false;
241        }
242
243        value.SetClangType (clang_type);
244        value_list.PushValue(value);
245    }
246
247    if (!abi->GetArgumentValues (*thread, value_list))
248    {
249        result.AppendError ("Couldn't get argument values");
250        result.SetStatus (eReturnStatusFailed);
251        return false;
252    }
253
254    result.GetOutputStream ().Printf("Arguments : \n");
255
256    for (arg_index = 0; arg_index < num_args; ++arg_index)
257    {
258        result.GetOutputStream ().Printf ("%zu (%s): ", arg_index, args.GetArgumentAtIndex (arg_index));
259        value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ());
260        result.GetOutputStream ().Printf("\n");
261    }
262
263    return result.Succeeded();
264}
265
266OptionDefinition
267CommandObjectArgs::CommandOptions::g_option_table[] =
268{
269    { LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."},
270    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
271};
272
273