blob: 9a1a7977d781c840a091eaf9afaf44ab6c95a43f [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectCall.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 "CommandObjectCall.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Jim Ingham84cdc152010-06-15 19:49:27 +000016#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000017#include "lldb/Core/Value.h"
18#include "lldb/Expression/ClangExpression.h"
19#include "lldb/Expression/ClangExpressionVariable.h"
20#include "lldb/Expression/ClangFunction.h"
21#include "lldb/Host/Host.h"
22#include "lldb/Interpreter/CommandInterpreter.h"
Greg Clayton63094e02010-06-23 01:19:29 +000023#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000024#include "lldb/Interpreter/CommandReturnObject.h"
25#include "lldb/Symbol/ObjectFile.h"
26#include "lldb/Symbol/Variable.h"
27#include "lldb/Target/Process.h"
28#include "lldb/Target/Target.h"
29#include "lldb/Target/StackFrame.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
34// This command is a toy. I'm just using it to have a way to construct the arguments to
35// calling functions.
36//
37
38CommandObjectCall::CommandOptions::CommandOptions () :
39 Options()
40{
41 // Keep only one place to reset the values to their defaults
42 ResetOptionValues();
43}
44
45
46CommandObjectCall::CommandOptions::~CommandOptions ()
47{
48}
49
50Error
51CommandObjectCall::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
52{
53 Error error;
54
55 char short_option = (char) m_getopt_table[option_idx].val;
56
57 switch (short_option)
58 {
59 case 'l':
60 if (language.SetLanguageFromCString (option_arg) == false)
61 {
62 error.SetErrorStringWithFormat("Invalid language option argument '%s'.\n", option_arg);
63 }
64 break;
65
66 case 'g':
67 debug = true;
68 break;
69
70 case 'f':
71 error = Args::StringToFormat(option_arg,format);
72 break;
73
74 case 'n':
75 noexecute = true;
76 break;
77
78 case 'a':
79 use_abi = true;
80 break;
81
82 default:
83 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
84 break;
85 }
86
87 return error;
88}
89
90void
91CommandObjectCall::CommandOptions::ResetOptionValues ()
92{
93 Options::ResetOptionValues();
94 language.Clear();
95 debug = false;
96 format = eFormatDefault;
97 show_types = true;
98 show_summary = true;
99 noexecute = false;
100 use_abi = false;
101}
102
103const lldb::OptionDefinition*
104CommandObjectCall::CommandOptions::GetDefinitions ()
105{
106 return g_option_table;
107}
108
109CommandObjectCall::CommandObjectCall () :
110 CommandObject (
111 "call",
112 "Call a function.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000113 //"call <return_type> <function-name> [[<arg1-type> <arg1-value>] ... <argn-type> <argn-value>] [<cmd-options>]",
114 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000115 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
116{
Caroline Tice43b014a2010-10-04 22:28:36 +0000117 CommandArgumentEntry arg1;
118 CommandArgumentEntry arg2;
119 CommandArgumentEntry arg3;
120 CommandArgumentData return_type_arg;
121 CommandArgumentData function_name_arg;
122 CommandArgumentData arg_type_arg;
123 CommandArgumentData arg_value_arg;
124
125 // Define the first (and only) variant of this arg.
126 return_type_arg.arg_type = eArgTypeType;
127 return_type_arg.arg_repetition = eArgRepeatPlain;
128
129 arg1.push_back (return_type_arg);
130
131 function_name_arg.arg_type = eArgTypeFunctionName;
132 function_name_arg.arg_repetition = eArgTypePlain;
133
134 arg2.push_back (function_name_arg);
135
136 arg_type_arg.arg_type = eArgTypeArgType;
137 arg_type_arg.arg_repetition = eArgRepeatPairRangeOptional;
138
139 arg_value_arg.arg_type = eArgTypeValue;
140 arg_value_arg.arg_repetition = eArgRepeatPairRangeOptional;
141
142 arg3.push_back (arg_type_arg);
143 arg3.push_back (arg_value_arg);
144
145 // Push the data for the first argument into the m_arguments vector.
146 m_arguments.push_back (arg1);
147 m_arguments.push_back (arg2);
148 m_arguments.push_back (arg3);
Chris Lattner24943d22010-06-08 16:52:24 +0000149}
150
151CommandObjectCall::~CommandObjectCall ()
152{
153}
154
155Options *
156CommandObjectCall::GetOptions ()
157{
158 return &m_options;
159}
160
161bool
162CommandObjectCall::Execute
163(
164 Args &command,
Chris Lattner24943d22010-06-08 16:52:24 +0000165 CommandReturnObject &result
166)
167{
168 ConstString target_triple;
169 int num_args = command.GetArgumentCount();
170
Greg Clayton63094e02010-06-23 01:19:29 +0000171 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
172 if (exe_ctx.target)
173 exe_ctx.target->GetTargetTriple(target_triple);
Chris Lattner24943d22010-06-08 16:52:24 +0000174
175 if (!target_triple)
176 target_triple = Host::GetTargetTriple ();
177
Chris Lattner24943d22010-06-08 16:52:24 +0000178 if (exe_ctx.thread == NULL || exe_ctx.frame == NULL)
179 {
180 result.AppendError ("No currently selected thread and frame.");
181 result.SetStatus (eReturnStatusFailed);
182 return false;
183 }
184
185 if (num_args < 2)
186 {
187 result.AppendErrorWithFormat ("Invalid usage, should be: %s.\n", GetSyntax());
188 result.SetStatus (eReturnStatusFailed);
189 return false;
190 }
191
192 if ((num_args - 2) %2 != 0)
193 {
194 result.AppendErrorWithFormat ("Invalid usage - unmatched args & types, should be: %s.\n", GetSyntax());
195 result.SetStatus (eReturnStatusFailed);
196 return false;
197 }
198
199 if (target_triple)
200 {
201 //const char *return_type = command.GetArgumentAtIndex(0);
202 const char *function_name = command.GetArgumentAtIndex(1);
203 // Look up the called function:
Sean Callanan0fc73582010-07-27 00:55:47 +0000204
205 Function *target_fn = NULL;
206
207 SymbolContextList sc_list;
208
209 exe_ctx.frame->GetSymbolContext(eSymbolContextEverything).FindFunctionsByName(ConstString(function_name), false, sc_list);
Chris Lattner24943d22010-06-08 16:52:24 +0000210
Sean Callanan0fc73582010-07-27 00:55:47 +0000211 if (sc_list.GetSize() > 0)
212 {
213 SymbolContext sc;
214 sc_list.GetContextAtIndex(0, sc);
215 target_fn = sc.function;
216 }
217
Chris Lattner24943d22010-06-08 16:52:24 +0000218 // FIXME: If target_fn is NULL, we should look up the name as a symbol and use it and the provided
219 // return type.
220
221 if (target_fn == NULL)
222 {
223 result.AppendErrorWithFormat ("Could not find function '%s'.\n", function_name);
224 result.SetStatus (eReturnStatusFailed);
225 return false;
226 }
227
228 ValueList value_list;
229 // Okay, now parse arguments. For now we only accept basic types.
230 for (int i = 2; i < num_args; i+= 2)
231 {
232 const char *type_str = command.GetArgumentAtIndex(i);
233 const char *value_str = command.GetArgumentAtIndex(i + 1);
234 bool success;
235 if (strcmp(type_str, "int") == 0
236 || strcmp(type_str, "int32_t") == 0)
237 {
238 value_list.PushValue(Value(Args::StringToSInt32(value_str, 0, 0, &success)));
239 }
240 else if (strcmp (type_str, "int64_t") == 0)
241 {
242 value_list.PushValue(Value(Args::StringToSInt64(value_str, 0, 0, &success)));
243 }
244 else if (strcmp(type_str, "uint") == 0
245 || strcmp(type_str, "uint32_t") == 0)
246 {
247 value_list.PushValue(Value(Args::StringToUInt32(value_str, 0, 0, &success)));
248 }
249 else if (strcmp (type_str, "uint64_t") == 0)
250 {
251 value_list.PushValue(Value(Args::StringToUInt64(value_str, 0, 0, &success)));
252 }
253 else if (strcmp (type_str, "cstr") == 0)
254 {
255 Value val ((intptr_t)value_str);
256 val.SetValueType (Value::eValueTypeHostAddress);
257
258
Greg Clayton63094e02010-06-23 01:19:29 +0000259 void *cstr_type = exe_ctx.target->GetScratchClangASTContext()->GetCStringType(true);
Greg Clayton6916e352010-11-13 03:52:47 +0000260 val.SetContext (Value::eContextTypeClangType, cstr_type);
Chris Lattner24943d22010-06-08 16:52:24 +0000261 value_list.PushValue(val);
262
263 success = true;
264 }
265
266 if (!success)
267 {
268 result.AppendErrorWithFormat ("Could not convert value: '%s' to type '%s'.\n", value_str, type_str);
269 result.SetStatus (eReturnStatusFailed);
270 return false;
271 }
272 }
273 // Okay, we have the function and the argument list and the return type. Now make a ClangFunction object and
274 // run it:
275
276 StreamString errors;
Greg Clayton63094e02010-06-23 01:19:29 +0000277 ClangFunction clang_fun (target_triple.GetCString(), *target_fn, exe_ctx.target->GetScratchClangASTContext(), value_list);
Chris Lattner24943d22010-06-08 16:52:24 +0000278 if (m_options.noexecute)
279 {
280 // Now write down the argument values for this call.
281 lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
282 if (!clang_fun.InsertFunction (exe_ctx, args_addr, errors))
283 {
284 result.AppendErrorWithFormat("Error inserting function: '%s'.\n", errors.GetData());
285 result.SetStatus (eReturnStatusFailed);
286 return false;
287 }
288 else
289 {
290 result.Succeeded();
291 return true;
292 }
293 }
294
295 ClangFunction::ExecutionResults return_status;
296 Value return_value;
297
Sean Callanan65dafa82010-08-27 01:01:44 +0000298 bool stop_others = true;
299 return_status = clang_fun.ExecuteFunction(exe_ctx, errors, stop_others, NULL, return_value);
Chris Lattner24943d22010-06-08 16:52:24 +0000300
301 // Now figure out what to do with the return value.
302 if (return_status == ClangFunction::eExecutionSetupError)
303 {
304 result.AppendErrorWithFormat("Error setting up function execution: '%s'.\n", errors.GetData());
305 result.SetStatus (eReturnStatusFailed);
306 return false;
307 }
308 else if (return_status != ClangFunction::eExecutionCompleted)
309 {
310 result.AppendWarningWithFormat("Interrupted while calling function: '%s'.\n", errors.GetData());
311 result.SetStatus(eReturnStatusSuccessFinishNoResult);
312 return true;
313 }
314 else
315 {
316 // Now print out the result.
317 result.GetOutputStream().Printf("Return value: ");
318 return_value.Dump(&(result.GetOutputStream()));
319 result.Succeeded();
320 }
321
322 }
323 else
324 {
325 result.AppendError ("invalid target triple");
326 result.SetStatus (eReturnStatusFailed);
327 }
328 return result.Succeeded();
329}
330
331lldb::OptionDefinition
332CommandObjectCall::CommandOptions::g_option_table[] =
333{
Greg Clayton12bec712010-06-28 21:30:43 +0000334{ LLDB_OPT_SET_1, false, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."},
Jim Ingham34e9a982010-06-15 18:47:14 +0000335{ LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."},
336{ LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable verbose debug logging of the expression parsing and evaluation."},
337{ LLDB_OPT_SET_1, false, "noexecute", 'n', no_argument, NULL, 0, "no execute", "Only JIT and copy the wrapper & arguments, but don't execute."},
Greg Claytonfe424a92010-09-18 03:37:20 +0000338{ LLDB_OPT_SET_1, false, "use-abi", 'a', no_argument, NULL, 0, NULL, "Use the ABI instead of the JIT to marshall arguments."},
Chris Lattner24943d22010-06-08 16:52:24 +0000339{ 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
340};
341