blob: e47d15da240314202f3e0793ec95e20b7ed61c4e [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectMemory.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 "CommandObjectMemory.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/DataExtractor.h"
Greg Clayton63094e02010-06-23 01:19:29 +000018#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000020#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton63094e02010-06-23 01:19:29 +000021#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton63094e02010-06-23 01:19:29 +000023#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/Options.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000025#include "lldb/Interpreter/OptionGroupFormat.h"
26#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton56bbdaf2011-04-28 20:55:26 +000027#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Sean Callanan3e80cd92011-10-12 02:08:07 +000028#include "lldb/Symbol/ClangNamespaceDecl.h"
Chris Lattner24943d22010-06-08 16:52:24 +000029#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000030#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000031
32using namespace lldb;
33using namespace lldb_private;
34
Greg Clayton56bbdaf2011-04-28 20:55:26 +000035static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000036g_option_table[] =
37{
Greg Clayton57b3c6b2011-04-27 22:04:39 +000038 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
39 { LLDB_OPT_SET_2, false, "binary" ,'b', no_argument , NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
40 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
41};
42
43
44
45class OptionGroupReadMemory : public OptionGroup
46{
47public:
48
49 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000050 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000051 m_output_as_binary (false),
52 m_view_as_type()
53 {
54 }
55
56 virtual
57 ~OptionGroupReadMemory ()
58 {
59 }
60
61
62 virtual uint32_t
63 GetNumDefinitions ()
64 {
65 return sizeof (g_option_table) / sizeof (OptionDefinition);
66 }
67
68 virtual const OptionDefinition*
69 GetDefinitions ()
70 {
71 return g_option_table;
72 }
73
74 virtual Error
75 SetOptionValue (CommandInterpreter &interpreter,
76 uint32_t option_idx,
77 const char *option_arg)
78 {
79 Error error;
80 char short_option = (char) g_option_table[option_idx].short_option;
81
82 switch (short_option)
83 {
84 case 'l':
85 error = m_num_per_line.SetValueFromCString (option_arg);
86 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000087 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000088 break;
Greg Claytona42880a2011-10-25 06:44:01 +000089
Greg Clayton57b3c6b2011-04-27 22:04:39 +000090 case 'b':
91 m_output_as_binary = true;
92 break;
93
94 case 't':
95 error = m_view_as_type.SetValueFromCString (option_arg);
96 break;
97
98 default:
Greg Clayton9c236732011-10-26 00:56:27 +000099 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000100 break;
101 }
102 return error;
103 }
104
105 virtual void
106 OptionParsingStarting (CommandInterpreter &interpreter)
107 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000108 m_num_per_line.Clear();
109 m_output_as_binary = false;
110 m_view_as_type.Clear();
111 }
112
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000113 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000114 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000115 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000116 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000117 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
118 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000119 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000120 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000121 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000122
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000123 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000124 {
125 default:
126 break;
127
128 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000129 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000130 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000131 if (!num_per_line_option_set)
132 m_num_per_line = 1;
133 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000134 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000135 break;
136
137 case eFormatCString:
138 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000139
140 case eFormatInstruction:
141 if (count_option_set)
142 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue();
143 m_num_per_line = 1;
144 break;
145
146 case eFormatAddressInfo:
147 if (!byte_size_option_set)
148 byte_size_value = target->GetArchitecture().GetAddressByteSize();
149 m_num_per_line = 1;
150 if (!count_option_set)
151 format_options.GetCountValue() = 8;
152 break;
153
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000154 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000155 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000156 if (!num_per_line_option_set)
157 m_num_per_line = 4;
158 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000159 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000160 break;
161
162 case eFormatBinary:
163 case eFormatFloat:
164 case eFormatOctal:
165 case eFormatDecimal:
166 case eFormatEnum:
167 case eFormatUnicode16:
168 case eFormatUnicode32:
169 case eFormatUnsigned:
Greg Clayton24a6bd92011-10-27 17:55:14 +0000170 case eFormatHexFloat:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000171 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000172 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000173 if (!num_per_line_option_set)
174 m_num_per_line = 1;
175 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000176 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000177 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000178
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000179 case eFormatBytes:
180 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000181 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000182 {
Greg Claytona42880a2011-10-25 06:44:01 +0000183 if (byte_size_value > 1)
Johnny Chenbf9ba592012-03-06 01:17:59 +0000184 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n"
185 "\tconsider using a different display format or don't specify the byte size",
186 byte_size_value.GetCurrentValue());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000187 }
188 else
Greg Claytona42880a2011-10-25 06:44:01 +0000189 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000190 if (!num_per_line_option_set)
191 m_num_per_line = 16;
192 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000193 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000194 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000195 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000196 case eFormatChar:
197 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000198 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000199 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000200 if (!num_per_line_option_set)
201 m_num_per_line = 32;
202 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000203 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000204 break;
205 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000206 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000207 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000208 if (!num_per_line_option_set)
209 m_num_per_line = 1;
210 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000211 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000212 break;
213 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000214 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000215 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000216 if (!num_per_line_option_set)
217 {
Greg Claytona42880a2011-10-25 06:44:01 +0000218 switch (byte_size_value)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000219 {
220 case 1:
221 case 2:
222 m_num_per_line = 8;
223 break;
224 case 4:
225 m_num_per_line = 4;
226 break;
227 case 8:
228 m_num_per_line = 2;
229 break;
230 default:
231 m_num_per_line = 1;
232 break;
233 }
234 }
235 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000236 count_value = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000237 break;
238
239 case eFormatVectorOfChar:
240 case eFormatVectorOfSInt8:
241 case eFormatVectorOfUInt8:
242 case eFormatVectorOfSInt16:
243 case eFormatVectorOfUInt16:
244 case eFormatVectorOfSInt32:
245 case eFormatVectorOfUInt32:
246 case eFormatVectorOfSInt64:
247 case eFormatVectorOfUInt64:
248 case eFormatVectorOfFloat32:
249 case eFormatVectorOfFloat64:
250 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000251 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000252 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000253 if (!num_per_line_option_set)
254 m_num_per_line = 1;
255 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000256 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000257 break;
258 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000259 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000260 }
261
Greg Clayton902b5be2011-10-26 04:32:38 +0000262 bool
263 AnyOptionWasSet () const
264 {
265 return m_num_per_line.OptionWasSet() ||
266 m_output_as_binary ||
267 m_view_as_type.OptionWasSet();
268 }
269
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000270 OptionValueUInt64 m_num_per_line;
271 bool m_output_as_binary;
272 OptionValueString m_view_as_type;
273};
274
275
276
Chris Lattner24943d22010-06-08 16:52:24 +0000277//----------------------------------------------------------------------
278// Read memory from the inferior process
279//----------------------------------------------------------------------
280class CommandObjectMemoryRead : public CommandObject
281{
282public:
283
Greg Clayton238c0a12010-09-18 01:14:36 +0000284 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
285 CommandObject (interpreter,
286 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000287 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000288 NULL,
Jim Ingham8cc3f692011-07-09 00:55:34 +0000289 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000290 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000291 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000292 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000293 m_outfile_options (),
Greg Clayton902b5be2011-10-26 04:32:38 +0000294 m_varobj_options(),
295 m_next_addr(LLDB_INVALID_ADDRESS),
296 m_prev_byte_size(0),
297 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
298 m_prev_memory_options (),
299 m_prev_outfile_options (),
300 m_prev_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000301 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000302 CommandArgumentEntry arg1;
303 CommandArgumentEntry arg2;
304 CommandArgumentData start_addr_arg;
305 CommandArgumentData end_addr_arg;
306
307 // Define the first (and only) variant of this arg.
308 start_addr_arg.arg_type = eArgTypeStartAddress;
309 start_addr_arg.arg_repetition = eArgRepeatPlain;
310
311 // There is only one variant this argument could be; put it into the argument entry.
312 arg1.push_back (start_addr_arg);
313
314 // Define the first (and only) variant of this arg.
315 end_addr_arg.arg_type = eArgTypeEndAddress;
316 end_addr_arg.arg_repetition = eArgRepeatOptional;
317
318 // There is only one variant this argument could be; put it into the argument entry.
319 arg2.push_back (end_addr_arg);
320
321 // Push the data for the first argument into the m_arguments vector.
322 m_arguments.push_back (arg1);
323 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000324
Greg Claytona42880a2011-10-25 06:44:01 +0000325 // Add the "--format" and "--count" options to group 1 and 3
326 m_option_group.Append (&m_format_options,
327 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000328 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000329 m_option_group.Append (&m_format_options,
330 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000331 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Claytona42880a2011-10-25 06:44:01 +0000332 // Add the "--size" option to group 1 and 2
333 m_option_group.Append (&m_format_options,
334 OptionGroupFormat::OPTION_GROUP_SIZE,
335 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000336 m_option_group.Append (&m_memory_options);
337 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000338 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000339 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000340 }
341
342 virtual
343 ~CommandObjectMemoryRead ()
344 {
345 }
346
347 Options *
348 GetOptions ()
349 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000350 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000351 }
352
Greg Clayton902b5be2011-10-26 04:32:38 +0000353 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
354 {
355 return m_cmd_name.c_str();
356 }
357
Chris Lattner24943d22010-06-08 16:52:24 +0000358 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000359 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000360 CommandReturnObject &result)
361 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000362 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000363 Target *target = exe_ctx.GetTargetPtr();
364 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000365 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000366 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000367 result.SetStatus(eReturnStatusFailed);
368 return false;
369 }
370 const size_t argc = command.GetArgumentCount();
371
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000372
Greg Clayton902b5be2011-10-26 04:32:38 +0000373 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000374 {
375 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
376 result.SetStatus(eReturnStatusFailed);
377 return false;
378 }
379
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000380 ClangASTType clang_ast_type;
381 Error error;
382
383 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000384 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
385 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000386 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000387 // We are viewing memory as a type
388 SymbolContext sc;
389 const bool append = true;
390 TypeList type_list;
391 uint32_t reference_count = 0;
392 uint32_t pointer_count = 0;
393 size_t idx;
394 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
395 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
396 std::string type_str(view_as_type_cstr);
397
398 // Remove all instances of g_keywords that are followed by spaces
399 for (size_t i = 0; i < g_num_keywords; ++i)
400 {
401 const char *keyword = g_keywords[i];
402 int keyword_len = ::strlen (keyword);
403 while ((idx = type_str.find (keyword)) != std::string::npos)
404 {
405 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
406 type_str.erase(idx, keyword_len+1);
407 }
408 }
409 bool done = type_str.empty();
410 //
411 idx = type_str.find_first_not_of (" \t");
412 if (idx > 0 && idx != std::string::npos)
413 type_str.erase (0, idx);
414 while (!done)
415 {
416 // Strip trailing spaces
417 if (type_str.empty())
418 done = true;
419 else
420 {
421 switch (type_str[type_str.size()-1])
422 {
423 case '*':
424 ++pointer_count;
425 // fall through...
426 case ' ':
427 case '\t':
428 type_str.erase(type_str.size()-1);
429 break;
430
431 case '&':
432 if (reference_count == 0)
433 {
434 reference_count = 1;
435 type_str.erase(type_str.size()-1);
436 }
437 else
438 {
439 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
440 result.SetStatus(eReturnStatusFailed);
441 return false;
442 }
443 break;
444
445 default:
446 done = true;
447 break;
448 }
449 }
450 }
451
452 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000453 StackFrame *frame = exe_ctx.GetFramePtr();
454 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000455 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000456 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000457 if (sc.module_sp)
458 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000459 sc.module_sp->FindTypes (sc,
460 lookup_type_name,
461 NULL,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000462 append,
463 1,
464 type_list);
465 }
466 }
467 if (type_list.GetSize() == 0)
468 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000469 target->GetImages().FindTypes (sc,
470 lookup_type_name,
471 append,
472 1,
473 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000474 }
475
476 if (type_list.GetSize() == 0)
477 {
478 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
479 lookup_type_name.GetCString(),
480 view_as_type_cstr);
481 result.SetStatus(eReturnStatusFailed);
482 return false;
483 }
484
485 TypeSP type_sp (type_list.GetTypeAtIndex(0));
486 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
487
488 while (pointer_count > 0)
489 {
490 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
491 if (pointer_type)
492 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
493 else
494 {
495 result.AppendError ("unable make a pointer type\n");
496 result.SetStatus(eReturnStatusFailed);
497 return false;
498 }
499 --pointer_count;
500 }
501
Greg Claytona42880a2011-10-25 06:44:01 +0000502 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000503
Greg Claytona42880a2011-10-25 06:44:01 +0000504 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000505 {
506 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
507 view_as_type_cstr);
508 result.SetStatus(eReturnStatusFailed);
509 return false;
510 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000511
Greg Claytona42880a2011-10-25 06:44:01 +0000512 if (!m_format_options.GetCountValue().OptionWasSet())
513 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000514 }
515 else
516 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000517 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000518 }
519
520 // Look for invalid combinations of settings
521 if (error.Fail())
522 {
523 result.AppendErrorWithFormat("%s", error.AsCString());
524 result.SetStatus(eReturnStatusFailed);
525 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000526 }
527
Greg Clayton902b5be2011-10-26 04:32:38 +0000528 lldb::addr_t addr;
529 size_t total_byte_size = 0;
530 if (argc == 0)
531 {
532 // Use the last address and byte size and all options as they were
533 // if no options have been set
534 addr = m_next_addr;
535 total_byte_size = m_prev_byte_size;
536 if (!m_format_options.AnyOptionWasSet() &&
537 !m_memory_options.AnyOptionWasSet() &&
538 !m_outfile_options.AnyOptionWasSet() &&
539 !m_varobj_options.AnyOptionWasSet())
540 {
541 m_format_options = m_prev_format_options;
542 m_memory_options = m_prev_memory_options;
543 m_outfile_options = m_prev_outfile_options;
544 m_varobj_options = m_prev_varobj_options;
545 }
546 }
547
Greg Claytona42880a2011-10-25 06:44:01 +0000548 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
549 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000550 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000551
Chris Lattner24943d22010-06-08 16:52:24 +0000552 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000553 {
554 total_byte_size = item_count * item_byte_size;
555 if (total_byte_size == 0)
556 total_byte_size = 32;
557 }
Chris Lattner24943d22010-06-08 16:52:24 +0000558
Greg Clayton902b5be2011-10-26 04:32:38 +0000559 if (argc > 0)
560 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000561
562 if (addr == LLDB_INVALID_ADDRESS)
563 {
564 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
565 result.SetStatus(eReturnStatusFailed);
566 return false;
567 }
568
569 if (argc == 2)
570 {
571 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
572 if (end_addr == LLDB_INVALID_ADDRESS)
573 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000574 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000575 result.SetStatus(eReturnStatusFailed);
576 return false;
577 }
578 else if (end_addr <= addr)
579 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000580 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
Chris Lattner24943d22010-06-08 16:52:24 +0000581 result.SetStatus(eReturnStatusFailed);
582 return false;
583 }
Greg Claytona42880a2011-10-25 06:44:01 +0000584 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000585 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000586 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner24943d22010-06-08 16:52:24 +0000587 result.SetStatus(eReturnStatusFailed);
588 return false;
589 }
590
591 total_byte_size = end_addr - addr;
592 item_count = total_byte_size / item_byte_size;
593 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000594
595 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000596 size_t bytes_read = 0;
597 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000598 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000599 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000600 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000601 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000602 if (bytes_read == 0)
603 {
604 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
605 result.AppendError(error.AsCString());
606 result.SetStatus(eReturnStatusFailed);
607 return false;
608 }
609
610 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000611 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
Greg Clayton902b5be2011-10-26 04:32:38 +0000612 else
613 {
614 m_next_addr = addr + bytes_read;
615 m_prev_byte_size = bytes_read;
616 m_prev_format_options = m_format_options;
617 m_prev_memory_options = m_memory_options;
618 m_prev_outfile_options = m_outfile_options;
619 m_prev_varobj_options = m_varobj_options;
620 }
Chris Lattner24943d22010-06-08 16:52:24 +0000621 }
622
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000623 StreamFile outfile_stream;
624 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000625 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
626 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000627 {
628 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000629 outfile_spec.GetPath (path, sizeof(path));
630
631 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
632 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
633 if (append)
634 open_options |= File::eOpenOptionAppend;
635
636 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000637 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000638 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000639 {
640 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
641 if (bytes_written > 0)
642 {
643 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
644 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000645 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000646 path);
647 return true;
648 }
649 else
650 {
651 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
652 result.SetStatus(eReturnStatusFailed);
653 return false;
654 }
655 }
656 else
657 {
658 // We are going to write ASCII to the file just point the
659 // output_stream to our outfile_stream...
660 output_stream = &outfile_stream;
661 }
662 }
663 else
664 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000665 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000666 result.SetStatus(eReturnStatusFailed);
667 return false;
668 }
669 }
670 else
671 {
672 output_stream = &result.GetOutputStream();
673 }
674
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000675
Greg Clayton24a6bd92011-10-27 17:55:14 +0000676 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000677 if (clang_ast_type.GetOpaqueQualType())
678 {
679 for (uint32_t i = 0; i<item_count; ++i)
680 {
681 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000682 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000683 StreamString name_strm;
684 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000685 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000686 name_strm.GetString().c_str(),
687 address,
688 clang_ast_type));
689 if (valobj_sp)
690 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000691 if (format != eFormatDefault)
692 valobj_sp->SetFormat (format);
693
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000694 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000695
Enrico Granata3069c622012-03-01 04:24:26 +0000696 ValueObject::DumpValueObjectOptions options;
697 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
698 .SetMaximumDepth(m_varobj_options.max_depth)
699 .SetShowLocation(m_varobj_options.show_location)
700 .SetShowTypes(m_varobj_options.show_types)
701 .SetUseObjectiveC(m_varobj_options.use_objc)
702 .SetScopeChecked(scope_already_checked)
703 .SetFlatOutput(m_varobj_options.flat_output)
704 .SetUseSyntheticValue(m_varobj_options.be_raw ? lldb::eNoSyntheticFilter : (m_varobj_options.use_synth ? lldb::eUseSyntheticFilter : lldb::eNoSyntheticFilter) )
705 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
706 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
707 .SetFormat(format)
708 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000709 ValueObject::DumpValueObject (*output_stream,
710 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000711 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000712 }
713 else
714 {
715 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
716 view_as_type_cstr,
717 name_strm.GetString().c_str());
718 result.SetStatus(eReturnStatusFailed);
719 return false;
720 }
721 }
722 return true;
723 }
724
725 result.SetStatus(eReturnStatusSuccessFinishResult);
726 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000727 target->GetArchitecture().GetByteOrder(),
728 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000729
730
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000731 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000732 uint32_t bytes_dumped = data.Dump (output_stream,
733 0,
734 m_format_options.GetFormat(),
735 item_byte_size,
736 item_count,
737 num_per_line,
738 addr,
739 0,
740 0,
741 exe_scope);
742 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000743 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000744 return true;
745 }
746
747protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000748 OptionGroupOptions m_option_group;
749 OptionGroupFormat m_format_options;
750 OptionGroupReadMemory m_memory_options;
751 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000752 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000753 lldb::addr_t m_next_addr;
754 lldb::addr_t m_prev_byte_size;
755 OptionGroupFormat m_prev_format_options;
756 OptionGroupReadMemory m_prev_memory_options;
757 OptionGroupOutputFile m_prev_outfile_options;
758 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000759};
760
Greg Claytona42880a2011-10-25 06:44:01 +0000761
762OptionDefinition
763g_memory_write_option_table[] =
764{
765{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
766{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
767};
768
769
Chris Lattner24943d22010-06-08 16:52:24 +0000770//----------------------------------------------------------------------
771// Write memory to the inferior process
772//----------------------------------------------------------------------
773class CommandObjectMemoryWrite : public CommandObject
774{
775public:
776
Greg Claytona42880a2011-10-25 06:44:01 +0000777 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000778 {
779 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000780 OptionGroupWriteMemory () :
781 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000782 {
Chris Lattner24943d22010-06-08 16:52:24 +0000783 }
784
785 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000786 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000787 {
788 }
789
Greg Claytona42880a2011-10-25 06:44:01 +0000790 virtual uint32_t
791 GetNumDefinitions ()
792 {
793 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
794 }
795
796 virtual const OptionDefinition*
797 GetDefinitions ()
798 {
799 return g_memory_write_option_table;
800 }
801
Chris Lattner24943d22010-06-08 16:52:24 +0000802 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000803 SetOptionValue (CommandInterpreter &interpreter,
804 uint32_t option_idx,
805 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000806 {
807 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000808 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
809
Chris Lattner24943d22010-06-08 16:52:24 +0000810 switch (short_option)
811 {
Greg Claytona42880a2011-10-25 06:44:01 +0000812 case 'i':
813 m_infile.SetFile (option_arg, true);
814 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000815 {
Greg Claytona42880a2011-10-25 06:44:01 +0000816 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000817 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000818 }
Greg Claytona42880a2011-10-25 06:44:01 +0000819 break;
820
821 case 'o':
822 {
823 bool success;
824 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
825 if (!success)
826 {
Greg Clayton9c236732011-10-26 00:56:27 +0000827 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000828 }
829 }
830 break;
831
832 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000833 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000834 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000835 }
836 return error;
837 }
Greg Claytona42880a2011-10-25 06:44:01 +0000838
839 virtual void
840 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000841 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000842 m_infile.Clear();
843 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000844 }
845
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000846 FileSpec m_infile;
847 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000848 };
849
Greg Clayton238c0a12010-09-18 01:14:36 +0000850 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
851 CommandObject (interpreter,
852 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000853 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000854 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
855 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000856 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000857 m_option_group (interpreter),
858 m_format_options (eFormatBytes, 1, UINT64_MAX),
859 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000860 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000861 CommandArgumentEntry arg1;
862 CommandArgumentEntry arg2;
863 CommandArgumentData addr_arg;
864 CommandArgumentData value_arg;
865
866 // Define the first (and only) variant of this arg.
867 addr_arg.arg_type = eArgTypeAddress;
868 addr_arg.arg_repetition = eArgRepeatPlain;
869
870 // There is only one variant this argument could be; put it into the argument entry.
871 arg1.push_back (addr_arg);
872
873 // Define the first (and only) variant of this arg.
874 value_arg.arg_type = eArgTypeValue;
875 value_arg.arg_repetition = eArgRepeatPlus;
876
877 // There is only one variant this argument could be; put it into the argument entry.
878 arg2.push_back (value_arg);
879
880 // Push the data for the first argument into the m_arguments vector.
881 m_arguments.push_back (arg1);
882 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000883
884 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
885 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
886 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
887 m_option_group.Finalize();
888
Chris Lattner24943d22010-06-08 16:52:24 +0000889 }
890
891 virtual
892 ~CommandObjectMemoryWrite ()
893 {
894 }
895
896 Options *
897 GetOptions ()
898 {
Greg Claytona42880a2011-10-25 06:44:01 +0000899 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000900 }
901
902 bool
903 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
904 {
905 if (total_byte_size > 8)
906 return false;
907
908 if (total_byte_size == 8)
909 return true;
910
911 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
912 return uval64 <= max;
913 }
914
915 bool
916 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
917 {
918 if (total_byte_size > 8)
919 return false;
920
921 if (total_byte_size == 8)
922 return true;
923
924 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
925 const int64_t min = ~(max);
926 return min <= sval64 && sval64 <= max;
927 }
928
929 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000930 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000931 CommandReturnObject &result)
932 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000933 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000934 if (process == NULL)
935 {
936 result.AppendError("need a process to read memory");
937 result.SetStatus(eReturnStatusFailed);
938 return false;
939 }
940
941 const size_t argc = command.GetArgumentCount();
942
Greg Claytona42880a2011-10-25 06:44:01 +0000943 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000944 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000945 if (argc < 1)
946 {
947 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
948 result.SetStatus(eReturnStatusFailed);
949 return false;
950 }
951 }
952 else if (argc < 2)
953 {
954 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000955 result.SetStatus(eReturnStatusFailed);
956 return false;
957 }
958
Chris Lattner24943d22010-06-08 16:52:24 +0000959 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000960 process->GetTarget().GetArchitecture().GetAddressByteSize(),
961 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000962
Greg Claytona42880a2011-10-25 06:44:01 +0000963 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
964 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000965
Chris Lattner24943d22010-06-08 16:52:24 +0000966 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
967
968 if (addr == LLDB_INVALID_ADDRESS)
969 {
970 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
971 result.SetStatus(eReturnStatusFailed);
972 return false;
973 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000974
Greg Claytona42880a2011-10-25 06:44:01 +0000975 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000976 {
977 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000978 if (item_byte_size > 0)
979 length = item_byte_size;
980 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000981 if (data_sp)
982 {
983 length = data_sp->GetByteSize();
984 if (length > 0)
985 {
986 Error error;
987 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
988
989 if (bytes_written == length)
990 {
991 // All bytes written
992 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
993 result.SetStatus(eReturnStatusSuccessFinishResult);
994 }
995 else if (bytes_written > 0)
996 {
997 // Some byte written
998 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
999 result.SetStatus(eReturnStatusSuccessFinishResult);
1000 }
1001 else
1002 {
1003 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1004 result.SetStatus(eReturnStatusFailed);
1005 }
1006 }
1007 }
1008 else
1009 {
1010 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1011 result.SetStatus(eReturnStatusFailed);
1012 }
1013 return result.Succeeded();
1014 }
Greg Claytona42880a2011-10-25 06:44:01 +00001015 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001016 {
Greg Claytona42880a2011-10-25 06:44:01 +00001017 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001018 item_byte_size = buffer.GetAddressByteSize();
1019 else
1020 item_byte_size = 1;
1021 }
1022
Chris Lattner24943d22010-06-08 16:52:24 +00001023 command.Shift(); // shift off the address argument
1024 uint64_t uval64;
1025 int64_t sval64;
1026 bool success = false;
1027 const uint32_t num_value_args = command.GetArgumentCount();
1028 uint32_t i;
1029 for (i=0; i<num_value_args; ++i)
1030 {
1031 const char *value_str = command.GetArgumentAtIndex(i);
1032
Greg Claytona42880a2011-10-25 06:44:01 +00001033 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001034 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001035 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001036 case eFormatFloat: // TODO: add support for floats soon
1037 case eFormatCharPrintable:
1038 case eFormatBytesWithASCII:
1039 case eFormatComplex:
1040 case eFormatEnum:
1041 case eFormatUnicode16:
1042 case eFormatUnicode32:
1043 case eFormatVectorOfChar:
1044 case eFormatVectorOfSInt8:
1045 case eFormatVectorOfUInt8:
1046 case eFormatVectorOfSInt16:
1047 case eFormatVectorOfUInt16:
1048 case eFormatVectorOfSInt32:
1049 case eFormatVectorOfUInt32:
1050 case eFormatVectorOfSInt64:
1051 case eFormatVectorOfUInt64:
1052 case eFormatVectorOfFloat32:
1053 case eFormatVectorOfFloat64:
1054 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001055 case eFormatOSType:
1056 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001057 case eFormatAddressInfo:
1058 case eFormatHexFloat:
1059 case eFormatInstruction:
Chris Lattner24943d22010-06-08 16:52:24 +00001060 result.AppendError("unsupported format for writing memory");
1061 result.SetStatus(eReturnStatusFailed);
1062 return false;
1063
1064 case eFormatDefault:
1065 case eFormatBytes:
1066 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001067 case eFormatPointer:
1068
Chris Lattner24943d22010-06-08 16:52:24 +00001069 // Decode hex bytes
1070 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1071 if (!success)
1072 {
1073 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1074 result.SetStatus(eReturnStatusFailed);
1075 return false;
1076 }
1077 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1078 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001079 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001080 result.SetStatus(eReturnStatusFailed);
1081 return false;
1082 }
1083 buffer.PutMaxHex64 (uval64, item_byte_size);
1084 break;
1085
1086 case eFormatBoolean:
1087 uval64 = Args::StringToBoolean(value_str, false, &success);
1088 if (!success)
1089 {
1090 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1091 result.SetStatus(eReturnStatusFailed);
1092 return false;
1093 }
1094 buffer.PutMaxHex64 (uval64, item_byte_size);
1095 break;
1096
1097 case eFormatBinary:
1098 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1099 if (!success)
1100 {
1101 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1102 result.SetStatus(eReturnStatusFailed);
1103 return false;
1104 }
1105 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1106 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001107 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001108 result.SetStatus(eReturnStatusFailed);
1109 return false;
1110 }
1111 buffer.PutMaxHex64 (uval64, item_byte_size);
1112 break;
1113
Greg Clayton307fa072011-06-17 23:50:44 +00001114 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001115 case eFormatChar:
1116 case eFormatCString:
1117 if (value_str[0])
1118 {
1119 size_t len = strlen (value_str);
1120 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001121 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001122 ++len;
1123 Error error;
1124 if (process->WriteMemory (addr, value_str, len, error) == len)
1125 {
1126 addr += len;
1127 }
1128 else
1129 {
1130 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1131 result.SetStatus(eReturnStatusFailed);
1132 return false;
1133 }
1134 }
1135 break;
1136
1137 case eFormatDecimal:
1138 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1139 if (!success)
1140 {
1141 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1142 result.SetStatus(eReturnStatusFailed);
1143 return false;
1144 }
1145 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1146 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001147 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001148 result.SetStatus(eReturnStatusFailed);
1149 return false;
1150 }
1151 buffer.PutMaxHex64 (sval64, item_byte_size);
1152 break;
1153
1154 case eFormatUnsigned:
1155 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1156 if (!success)
1157 {
1158 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1159 result.SetStatus(eReturnStatusFailed);
1160 return false;
1161 }
1162 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1163 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001164 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001165 result.SetStatus(eReturnStatusFailed);
1166 return false;
1167 }
1168 buffer.PutMaxHex64 (uval64, item_byte_size);
1169 break;
1170
1171 case eFormatOctal:
1172 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1173 if (!success)
1174 {
1175 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1176 result.SetStatus(eReturnStatusFailed);
1177 return false;
1178 }
1179 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1180 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001181 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001182 result.SetStatus(eReturnStatusFailed);
1183 return false;
1184 }
1185 buffer.PutMaxHex64 (uval64, item_byte_size);
1186 break;
1187 }
1188 }
1189
1190 if (!buffer.GetString().empty())
1191 {
1192 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001193 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001194 return true;
1195 else
1196 {
1197 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1198 result.SetStatus(eReturnStatusFailed);
1199 return false;
1200 }
1201 }
1202 return true;
1203 }
1204
1205protected:
Greg Claytona42880a2011-10-25 06:44:01 +00001206
1207 OptionGroupOptions m_option_group;
1208 OptionGroupFormat m_format_options;
1209 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001210};
1211
Chris Lattner24943d22010-06-08 16:52:24 +00001212
1213//-------------------------------------------------------------------------
1214// CommandObjectMemory
1215//-------------------------------------------------------------------------
1216
Greg Clayton63094e02010-06-23 01:19:29 +00001217CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001218 CommandObjectMultiword (interpreter,
1219 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001220 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001221 "memory <subcommand> [<subcommand-options>]")
1222{
Greg Clayton238c0a12010-09-18 01:14:36 +00001223 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1224 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001225}
1226
1227CommandObjectMemory::~CommandObjectMemory ()
1228{
1229}