blob: 1aa92fdcc848b1a458253c2232285bcd080aca5d [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{
38 { LLDB_OPT_SET_1|
39 LLDB_OPT_SET_2, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize ,"The size in bytes to use when displaying with the selected format."},
40 { LLDB_OPT_SET_1|
41 LLDB_OPT_SET_3, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount ,"The number of total items to display."},
42 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
43 { 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."},
44 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
45};
46
47
48
49class OptionGroupReadMemory : public OptionGroup
50{
51public:
52
53 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000054 m_byte_size (1,1),
55 m_count (8,8),
56 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000057 m_output_as_binary (false),
58 m_view_as_type()
59 {
60 }
61
62 virtual
63 ~OptionGroupReadMemory ()
64 {
65 }
66
67
68 virtual uint32_t
69 GetNumDefinitions ()
70 {
71 return sizeof (g_option_table) / sizeof (OptionDefinition);
72 }
73
74 virtual const OptionDefinition*
75 GetDefinitions ()
76 {
77 return g_option_table;
78 }
79
80 virtual Error
81 SetOptionValue (CommandInterpreter &interpreter,
82 uint32_t option_idx,
83 const char *option_arg)
84 {
85 Error error;
86 char short_option = (char) g_option_table[option_idx].short_option;
87
88 switch (short_option)
89 {
90 case 'l':
91 error = m_num_per_line.SetValueFromCString (option_arg);
92 if (m_num_per_line.GetCurrentValue() == 0)
93 error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
94 break;
95
96 case 'c':
97 error = m_count.SetValueFromCString (option_arg);
98 if (m_count.GetCurrentValue() == 0)
99 error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
100 break;
101
102 case 's':
103 error = m_byte_size.SetValueFromCString (option_arg);
104 if (m_byte_size.GetCurrentValue() == 0)
105 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
106 break;
107
108 case 'b':
109 m_output_as_binary = true;
110 break;
111
112 case 't':
113 error = m_view_as_type.SetValueFromCString (option_arg);
114 break;
115
116 default:
117 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
118 break;
119 }
120 return error;
121 }
122
123 virtual void
124 OptionParsingStarting (CommandInterpreter &interpreter)
125 {
126 m_byte_size.Clear();
127 m_count.Clear();
128 m_num_per_line.Clear();
129 m_output_as_binary = false;
130 m_view_as_type.Clear();
131 }
132
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000133 Error
134 FinalizeSettings (Target *target, const OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000135 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000136 Error error;
137 bool byte_size_option_set = m_byte_size.OptionWasSet();
138 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
139 const bool count_option_set = m_count.OptionWasSet();
140
141 uint32_t format_byte_size = format_options.GetByteSize();
142 if (byte_size_option_set)
143 {
144 if (format_byte_size > 0)
145 {
146 error.SetErrorString("can't specify the byte size in both the '--size <num>' option and the '--format [<byte-size>]<format-char>' options.");
147 return error;
148 }
149 }
150 else
151 {
152 if (format_byte_size != 0)
153 {
154 byte_size_option_set = true;
155 m_byte_size = format_byte_size;
156 }
157 }
158
159 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000160 {
161 default:
162 break;
163
164 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000165 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000166 m_byte_size = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000167 if (!num_per_line_option_set)
168 m_num_per_line = 1;
169 if (!count_option_set)
170 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000171 break;
172
173 case eFormatCString:
174 break;
175
176 case eFormatPointer:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000177 m_byte_size = target->GetArchitecture().GetAddressByteSize();
178 if (!num_per_line_option_set)
179 m_num_per_line = 4;
180 if (!count_option_set)
181 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000182 break;
183
184 case eFormatBinary:
185 case eFormatFloat:
186 case eFormatOctal:
187 case eFormatDecimal:
188 case eFormatEnum:
189 case eFormatUnicode16:
190 case eFormatUnicode32:
191 case eFormatUnsigned:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000192 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000193 m_byte_size = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000194 if (!num_per_line_option_set)
195 m_num_per_line = 1;
196 if (!count_option_set)
197 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000198 break;
199
200 case eFormatBytes:
201 case eFormatBytesWithASCII:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000202 if (m_byte_size.OptionWasSet())
203 {
204 if (m_byte_size > 1)
205 error.SetErrorString ("use --count option to specify an end address to display a number of bytes");
206 }
207 else
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000208 m_byte_size = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000209 if (!num_per_line_option_set)
210 m_num_per_line = 16;
211 if (!count_option_set)
212 m_count = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000213 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000214 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000215 case eFormatChar:
216 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000217 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000218 m_byte_size = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000219 if (!num_per_line_option_set)
220 m_num_per_line = 32;
221 if (!count_option_set)
222 m_count = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000223 break;
224 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000225 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000226 m_byte_size = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000227 if (!num_per_line_option_set)
228 m_num_per_line = 1;
229 if (!count_option_set)
230 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000231 break;
232 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000233 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000234 m_byte_size = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000235 if (!num_per_line_option_set)
236 {
237 switch (m_byte_size)
238 {
239 case 1:
240 case 2:
241 m_num_per_line = 8;
242 break;
243 case 4:
244 m_num_per_line = 4;
245 break;
246 case 8:
247 m_num_per_line = 2;
248 break;
249 default:
250 m_num_per_line = 1;
251 break;
252 }
253 }
254 if (!count_option_set)
255 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000256 break;
257
258 case eFormatVectorOfChar:
259 case eFormatVectorOfSInt8:
260 case eFormatVectorOfUInt8:
261 case eFormatVectorOfSInt16:
262 case eFormatVectorOfUInt16:
263 case eFormatVectorOfSInt32:
264 case eFormatVectorOfUInt32:
265 case eFormatVectorOfSInt64:
266 case eFormatVectorOfUInt64:
267 case eFormatVectorOfFloat32:
268 case eFormatVectorOfFloat64:
269 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000270 if (!byte_size_option_set)
271 m_byte_size = 128;
272 if (!num_per_line_option_set)
273 m_num_per_line = 1;
274 if (!count_option_set)
275 m_count = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000276 break;
277 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000278 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000279 }
280
281 OptionValueUInt64 m_byte_size;
282 OptionValueUInt64 m_count;
283 OptionValueUInt64 m_num_per_line;
284 bool m_output_as_binary;
285 OptionValueString m_view_as_type;
286};
287
288
289
Chris Lattner24943d22010-06-08 16:52:24 +0000290//----------------------------------------------------------------------
291// Read memory from the inferior process
292//----------------------------------------------------------------------
293class CommandObjectMemoryRead : public CommandObject
294{
295public:
296
Greg Clayton238c0a12010-09-18 01:14:36 +0000297 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
298 CommandObject (interpreter,
299 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000300 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000301 NULL,
Jim Ingham8cc3f692011-07-09 00:55:34 +0000302 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000303 m_option_group (interpreter),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000304 m_format_options (eFormatBytesWithASCII, 0, true),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000305 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000306 m_outfile_options (),
307 m_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000308 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000309 CommandArgumentEntry arg1;
310 CommandArgumentEntry arg2;
311 CommandArgumentData start_addr_arg;
312 CommandArgumentData end_addr_arg;
313
314 // Define the first (and only) variant of this arg.
315 start_addr_arg.arg_type = eArgTypeStartAddress;
316 start_addr_arg.arg_repetition = eArgRepeatPlain;
317
318 // There is only one variant this argument could be; put it into the argument entry.
319 arg1.push_back (start_addr_arg);
320
321 // Define the first (and only) variant of this arg.
322 end_addr_arg.arg_type = eArgTypeEndAddress;
323 end_addr_arg.arg_repetition = eArgRepeatOptional;
324
325 // There is only one variant this argument could be; put it into the argument entry.
326 arg2.push_back (end_addr_arg);
327
328 // Push the data for the first argument into the m_arguments vector.
329 m_arguments.push_back (arg1);
330 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000331
332 m_option_group.Append (&m_format_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
333 m_option_group.Append (&m_memory_options);
334 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 +0000335 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000336 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000337 }
338
339 virtual
340 ~CommandObjectMemoryRead ()
341 {
342 }
343
344 Options *
345 GetOptions ()
346 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000347 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000348 }
349
350 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000351 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000352 CommandReturnObject &result)
353 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000354 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000355 Target *target = exe_ctx.GetTargetPtr();
356 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000357 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000358 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000359 result.SetStatus(eReturnStatusFailed);
360 return false;
361 }
362 const size_t argc = command.GetArgumentCount();
363
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000364
Chris Lattner24943d22010-06-08 16:52:24 +0000365 if (argc == 0 || argc > 2)
366 {
367 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
368 result.SetStatus(eReturnStatusFailed);
369 return false;
370 }
371
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000372 ClangASTType clang_ast_type;
373 Error error;
374
375 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000376 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
377 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000378 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000379 // We are viewing memory as a type
380 SymbolContext sc;
381 const bool append = true;
382 TypeList type_list;
383 uint32_t reference_count = 0;
384 uint32_t pointer_count = 0;
385 size_t idx;
386 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
387 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
388 std::string type_str(view_as_type_cstr);
389
390 // Remove all instances of g_keywords that are followed by spaces
391 for (size_t i = 0; i < g_num_keywords; ++i)
392 {
393 const char *keyword = g_keywords[i];
394 int keyword_len = ::strlen (keyword);
395 while ((idx = type_str.find (keyword)) != std::string::npos)
396 {
397 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
398 type_str.erase(idx, keyword_len+1);
399 }
400 }
401 bool done = type_str.empty();
402 //
403 idx = type_str.find_first_not_of (" \t");
404 if (idx > 0 && idx != std::string::npos)
405 type_str.erase (0, idx);
406 while (!done)
407 {
408 // Strip trailing spaces
409 if (type_str.empty())
410 done = true;
411 else
412 {
413 switch (type_str[type_str.size()-1])
414 {
415 case '*':
416 ++pointer_count;
417 // fall through...
418 case ' ':
419 case '\t':
420 type_str.erase(type_str.size()-1);
421 break;
422
423 case '&':
424 if (reference_count == 0)
425 {
426 reference_count = 1;
427 type_str.erase(type_str.size()-1);
428 }
429 else
430 {
431 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
432 result.SetStatus(eReturnStatusFailed);
433 return false;
434 }
435 break;
436
437 default:
438 done = true;
439 break;
440 }
441 }
442 }
443
444 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000445 StackFrame *frame = exe_ctx.GetFramePtr();
446 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000447 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000448 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000449 if (sc.module_sp)
450 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000451 sc.module_sp->FindTypes (sc,
452 lookup_type_name,
453 NULL,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000454 append,
455 1,
456 type_list);
457 }
458 }
459 if (type_list.GetSize() == 0)
460 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000461 target->GetImages().FindTypes (sc,
462 lookup_type_name,
463 append,
464 1,
465 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000466 }
467
468 if (type_list.GetSize() == 0)
469 {
470 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
471 lookup_type_name.GetCString(),
472 view_as_type_cstr);
473 result.SetStatus(eReturnStatusFailed);
474 return false;
475 }
476
477 TypeSP type_sp (type_list.GetTypeAtIndex(0));
478 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
479
480 while (pointer_count > 0)
481 {
482 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
483 if (pointer_type)
484 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
485 else
486 {
487 result.AppendError ("unable make a pointer type\n");
488 result.SetStatus(eReturnStatusFailed);
489 return false;
490 }
491 --pointer_count;
492 }
493
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000494 m_memory_options.m_byte_size = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000495
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000496 if (m_memory_options.m_byte_size == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000497 {
498 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
499 view_as_type_cstr);
500 result.SetStatus(eReturnStatusFailed);
501 return false;
502 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000503
504 if (!m_memory_options.m_count.OptionWasSet())
505 m_memory_options.m_count = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000506 }
507 else
508 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000509 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000510 }
511
512 // Look for invalid combinations of settings
513 if (error.Fail())
514 {
515 result.AppendErrorWithFormat("%s", error.AsCString());
516 result.SetStatus(eReturnStatusFailed);
517 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000518 }
519
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000520 size_t item_count = m_memory_options.m_count.GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000521 const size_t item_byte_size = m_memory_options.m_byte_size;
522 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000523
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000524 size_t total_byte_size = item_count * item_byte_size;
Chris Lattner24943d22010-06-08 16:52:24 +0000525 if (total_byte_size == 0)
526 total_byte_size = 32;
527
528 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
529
530 if (addr == LLDB_INVALID_ADDRESS)
531 {
532 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
533 result.SetStatus(eReturnStatusFailed);
534 return false;
535 }
536
537 if (argc == 2)
538 {
539 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
540 if (end_addr == LLDB_INVALID_ADDRESS)
541 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000542 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000543 result.SetStatus(eReturnStatusFailed);
544 return false;
545 }
546 else if (end_addr <= addr)
547 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000548 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 +0000549 result.SetStatus(eReturnStatusFailed);
550 return false;
551 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000552 else if (m_memory_options.m_count.OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000553 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000554 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 +0000555 result.SetStatus(eReturnStatusFailed);
556 return false;
557 }
558
559 total_byte_size = end_addr - addr;
560 item_count = total_byte_size / item_byte_size;
561 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000562
563 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000564 size_t bytes_read = 0;
565 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000566 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000567 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Jim Ingham8cc3f692011-07-09 00:55:34 +0000568 Address address(NULL, addr);
Greg Clayton567e7f32011-09-22 04:58:26 +0000569 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000570 if (bytes_read == 0)
571 {
572 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
573 result.AppendError(error.AsCString());
574 result.SetStatus(eReturnStatusFailed);
575 return false;
576 }
577
578 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000579 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
Chris Lattner24943d22010-06-08 16:52:24 +0000580 }
581
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000582 StreamFile outfile_stream;
583 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000584 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
585 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000586 {
587 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000588 outfile_spec.GetPath (path, sizeof(path));
589
590 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
591 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
592 if (append)
593 open_options |= File::eOpenOptionAppend;
594
595 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000596 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000597 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000598 {
599 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
600 if (bytes_written > 0)
601 {
602 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
603 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000604 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000605 path);
606 return true;
607 }
608 else
609 {
610 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
611 result.SetStatus(eReturnStatusFailed);
612 return false;
613 }
614 }
615 else
616 {
617 // We are going to write ASCII to the file just point the
618 // output_stream to our outfile_stream...
619 output_stream = &outfile_stream;
620 }
621 }
622 else
623 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000624 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000625 result.SetStatus(eReturnStatusFailed);
626 return false;
627 }
628 }
629 else
630 {
631 output_stream = &result.GetOutputStream();
632 }
633
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000634
635 if (clang_ast_type.GetOpaqueQualType())
636 {
637 for (uint32_t i = 0; i<item_count; ++i)
638 {
639 addr_t item_addr = addr + (i * item_byte_size);
640 Address address (NULL, item_addr);
641 StreamString name_strm;
642 name_strm.Printf ("0x%llx", item_addr);
643 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
644 name_strm.GetString().c_str(),
645 address,
646 clang_ast_type));
647 if (valobj_sp)
648 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000649 if (format != eFormatDefault)
650 valobj_sp->SetFormat (format);
651
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000652 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000653
654 ValueObject::DumpValueObject (*output_stream,
655 valobj_sp.get(),
656 NULL,
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000657 m_varobj_options.ptr_depth,
658 0,
659 m_varobj_options.max_depth,
660 m_varobj_options.show_types,
661 m_varobj_options.show_location,
662 m_varobj_options.use_objc,
Jim Ingham10de7d12011-05-04 03:43:18 +0000663 m_varobj_options.use_dynamic,
Enrico Granata840eb262011-08-09 23:50:01 +0000664 m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000665 scope_already_checked,
Enrico Granata7f163b32011-07-16 01:22:04 +0000666 m_varobj_options.flat_output,
Enrico Granata018921d2011-08-12 02:00:06 +0000667 m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth,
668 m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000669 }
670 else
671 {
672 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
673 view_as_type_cstr,
674 name_strm.GetString().c_str());
675 result.SetStatus(eReturnStatusFailed);
676 return false;
677 }
678 }
679 return true;
680 }
681
682 result.SetStatus(eReturnStatusSuccessFinishResult);
683 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000684 target->GetArchitecture().GetByteOrder(),
685 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000686
687
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000688 assert (output_stream);
689 data.Dump (output_stream,
690 0,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000691 m_format_options.GetFormat(),
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000692 item_byte_size,
693 item_count,
694 num_per_line,
695 addr,
696 0,
697 0);
698 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000699 return true;
700 }
701
702protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000703 OptionGroupOptions m_option_group;
704 OptionGroupFormat m_format_options;
705 OptionGroupReadMemory m_memory_options;
706 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000707 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000708
Chris Lattner24943d22010-06-08 16:52:24 +0000709};
710
Chris Lattner24943d22010-06-08 16:52:24 +0000711//----------------------------------------------------------------------
712// Write memory to the inferior process
713//----------------------------------------------------------------------
714class CommandObjectMemoryWrite : public CommandObject
715{
716public:
717
718 class CommandOptions : public Options
719 {
720 public:
Greg Claytonf15996e2011-04-07 22:46:35 +0000721 CommandOptions (CommandInterpreter &interpreter) :
722 Options(interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000723 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000724 OptionParsingStarting();
Chris Lattner24943d22010-06-08 16:52:24 +0000725 }
726
727 virtual
728 ~CommandOptions ()
729 {
730 }
731
732 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000733 SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000734 {
735 Error error;
736 char short_option = (char) m_getopt_table[option_idx].val;
737 switch (short_option)
738 {
739 case 'f':
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000740 error = Args::StringToFormat (option_arg, m_format, &m_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +0000741 break;
742
743 case 's':
744 m_byte_size = Args::StringToUInt32 (option_arg, 0);
745 if (m_byte_size == 0)
746 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
747 break;
748
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000749 case 'i':
Greg Clayton537a7a82010-10-20 20:54:39 +0000750 m_infile.SetFile (option_arg, true);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000751 if (!m_infile.Exists())
752 {
753 m_infile.Clear();
754 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg);
755 }
756 break;
757
758 case 'o':
759 {
760 bool success;
761 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
762 if (!success)
763 {
764 error.SetErrorStringWithFormat("Invalid offset string '%s'\n", option_arg);
765 }
766 }
767 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000768
769 default:
770 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
771 break;
772 }
773 return error;
774 }
775
776 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000777 OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000778 {
Chris Lattner24943d22010-06-08 16:52:24 +0000779 m_format = eFormatBytes;
780 m_byte_size = 1;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000781 m_infile.Clear();
782 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000783 }
784
Greg Claytonb3448432011-03-24 21:19:54 +0000785 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000786 GetDefinitions ()
787 {
788 return g_option_table;
789 }
790
791 // Options table: Required for subclasses of Options.
792
Greg Claytonb3448432011-03-24 21:19:54 +0000793 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000794
795 // Instance variables to hold the values for command options.
796 lldb::Format m_format;
797 uint32_t m_byte_size;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000798 FileSpec m_infile;
799 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000800 };
801
Greg Clayton238c0a12010-09-18 01:14:36 +0000802 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
803 CommandObject (interpreter,
804 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000805 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000806 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
807 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000808 eFlagProcessMustBeLaunched),
809 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000810 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000811 CommandArgumentEntry arg1;
812 CommandArgumentEntry arg2;
813 CommandArgumentData addr_arg;
814 CommandArgumentData value_arg;
815
816 // Define the first (and only) variant of this arg.
817 addr_arg.arg_type = eArgTypeAddress;
818 addr_arg.arg_repetition = eArgRepeatPlain;
819
820 // There is only one variant this argument could be; put it into the argument entry.
821 arg1.push_back (addr_arg);
822
823 // Define the first (and only) variant of this arg.
824 value_arg.arg_type = eArgTypeValue;
825 value_arg.arg_repetition = eArgRepeatPlus;
826
827 // There is only one variant this argument could be; put it into the argument entry.
828 arg2.push_back (value_arg);
829
830 // Push the data for the first argument into the m_arguments vector.
831 m_arguments.push_back (arg1);
832 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000833 }
834
835 virtual
836 ~CommandObjectMemoryWrite ()
837 {
838 }
839
840 Options *
841 GetOptions ()
842 {
843 return &m_options;
844 }
845
846 bool
847 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
848 {
849 if (total_byte_size > 8)
850 return false;
851
852 if (total_byte_size == 8)
853 return true;
854
855 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
856 return uval64 <= max;
857 }
858
859 bool
860 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
861 {
862 if (total_byte_size > 8)
863 return false;
864
865 if (total_byte_size == 8)
866 return true;
867
868 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
869 const int64_t min = ~(max);
870 return min <= sval64 && sval64 <= max;
871 }
872
873 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000874 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000875 CommandReturnObject &result)
876 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000877 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000878 if (process == NULL)
879 {
880 result.AppendError("need a process to read memory");
881 result.SetStatus(eReturnStatusFailed);
882 return false;
883 }
884
885 const size_t argc = command.GetArgumentCount();
886
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000887 if (m_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000888 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000889 if (argc < 1)
890 {
891 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
892 result.SetStatus(eReturnStatusFailed);
893 return false;
894 }
895 }
896 else if (argc < 2)
897 {
898 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 +0000899 result.SetStatus(eReturnStatusFailed);
900 return false;
901 }
902
Chris Lattner24943d22010-06-08 16:52:24 +0000903 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000904 process->GetTarget().GetArchitecture().GetAddressByteSize(),
905 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000906
Greg Clayton54e7afa2010-07-09 20:39:50 +0000907 size_t item_byte_size = m_options.m_byte_size;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000908
Chris Lattner24943d22010-06-08 16:52:24 +0000909 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
910
911 if (addr == LLDB_INVALID_ADDRESS)
912 {
913 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
914 result.SetStatus(eReturnStatusFailed);
915 return false;
916 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000917
918 if (m_options.m_infile)
919 {
920 size_t length = SIZE_MAX;
921 if (m_options.m_byte_size > 0)
922 length = m_options.m_byte_size;
923 lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length));
924 if (data_sp)
925 {
926 length = data_sp->GetByteSize();
927 if (length > 0)
928 {
929 Error error;
930 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
931
932 if (bytes_written == length)
933 {
934 // All bytes written
935 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
936 result.SetStatus(eReturnStatusSuccessFinishResult);
937 }
938 else if (bytes_written > 0)
939 {
940 // Some byte written
941 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
942 result.SetStatus(eReturnStatusSuccessFinishResult);
943 }
944 else
945 {
946 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
947 result.SetStatus(eReturnStatusFailed);
948 }
949 }
950 }
951 else
952 {
953 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
954 result.SetStatus(eReturnStatusFailed);
955 }
956 return result.Succeeded();
957 }
958 else if (m_options.m_byte_size == 0)
959 {
960 if (m_options.m_format == eFormatPointer)
961 item_byte_size = buffer.GetAddressByteSize();
962 else
963 item_byte_size = 1;
964 }
965
Chris Lattner24943d22010-06-08 16:52:24 +0000966 command.Shift(); // shift off the address argument
967 uint64_t uval64;
968 int64_t sval64;
969 bool success = false;
970 const uint32_t num_value_args = command.GetArgumentCount();
971 uint32_t i;
972 for (i=0; i<num_value_args; ++i)
973 {
974 const char *value_str = command.GetArgumentAtIndex(i);
975
976 switch (m_options.m_format)
977 {
Greg Clayton3182eff2011-06-23 21:22:24 +0000978 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +0000979 case eFormatFloat: // TODO: add support for floats soon
980 case eFormatCharPrintable:
981 case eFormatBytesWithASCII:
982 case eFormatComplex:
983 case eFormatEnum:
984 case eFormatUnicode16:
985 case eFormatUnicode32:
986 case eFormatVectorOfChar:
987 case eFormatVectorOfSInt8:
988 case eFormatVectorOfUInt8:
989 case eFormatVectorOfSInt16:
990 case eFormatVectorOfUInt16:
991 case eFormatVectorOfSInt32:
992 case eFormatVectorOfUInt32:
993 case eFormatVectorOfSInt64:
994 case eFormatVectorOfUInt64:
995 case eFormatVectorOfFloat32:
996 case eFormatVectorOfFloat64:
997 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +0000998 case eFormatOSType:
999 case eFormatComplexInteger:
Chris Lattner24943d22010-06-08 16:52:24 +00001000 result.AppendError("unsupported format for writing memory");
1001 result.SetStatus(eReturnStatusFailed);
1002 return false;
1003
1004 case eFormatDefault:
1005 case eFormatBytes:
1006 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001007 case eFormatPointer:
1008
Chris Lattner24943d22010-06-08 16:52:24 +00001009 // Decode hex bytes
1010 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1011 if (!success)
1012 {
1013 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1014 result.SetStatus(eReturnStatusFailed);
1015 return false;
1016 }
1017 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1018 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001019 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 +00001020 result.SetStatus(eReturnStatusFailed);
1021 return false;
1022 }
1023 buffer.PutMaxHex64 (uval64, item_byte_size);
1024 break;
1025
1026 case eFormatBoolean:
1027 uval64 = Args::StringToBoolean(value_str, false, &success);
1028 if (!success)
1029 {
1030 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1031 result.SetStatus(eReturnStatusFailed);
1032 return false;
1033 }
1034 buffer.PutMaxHex64 (uval64, item_byte_size);
1035 break;
1036
1037 case eFormatBinary:
1038 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1039 if (!success)
1040 {
1041 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1042 result.SetStatus(eReturnStatusFailed);
1043 return false;
1044 }
1045 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1046 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001047 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 +00001048 result.SetStatus(eReturnStatusFailed);
1049 return false;
1050 }
1051 buffer.PutMaxHex64 (uval64, item_byte_size);
1052 break;
1053
Greg Clayton307fa072011-06-17 23:50:44 +00001054 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001055 case eFormatChar:
1056 case eFormatCString:
1057 if (value_str[0])
1058 {
1059 size_t len = strlen (value_str);
1060 // Include the NULL for C strings...
1061 if (m_options.m_format == eFormatCString)
1062 ++len;
1063 Error error;
1064 if (process->WriteMemory (addr, value_str, len, error) == len)
1065 {
1066 addr += len;
1067 }
1068 else
1069 {
1070 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1071 result.SetStatus(eReturnStatusFailed);
1072 return false;
1073 }
1074 }
1075 break;
1076
1077 case eFormatDecimal:
1078 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1079 if (!success)
1080 {
1081 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1082 result.SetStatus(eReturnStatusFailed);
1083 return false;
1084 }
1085 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1086 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001087 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 +00001088 result.SetStatus(eReturnStatusFailed);
1089 return false;
1090 }
1091 buffer.PutMaxHex64 (sval64, item_byte_size);
1092 break;
1093
1094 case eFormatUnsigned:
1095 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1096 if (!success)
1097 {
1098 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1099 result.SetStatus(eReturnStatusFailed);
1100 return false;
1101 }
1102 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1103 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001104 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 +00001105 result.SetStatus(eReturnStatusFailed);
1106 return false;
1107 }
1108 buffer.PutMaxHex64 (uval64, item_byte_size);
1109 break;
1110
1111 case eFormatOctal:
1112 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1113 if (!success)
1114 {
1115 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1116 result.SetStatus(eReturnStatusFailed);
1117 return false;
1118 }
1119 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1120 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001121 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 +00001122 result.SetStatus(eReturnStatusFailed);
1123 return false;
1124 }
1125 buffer.PutMaxHex64 (uval64, item_byte_size);
1126 break;
1127 }
1128 }
1129
1130 if (!buffer.GetString().empty())
1131 {
1132 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001133 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001134 return true;
1135 else
1136 {
1137 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1138 result.SetStatus(eReturnStatusFailed);
1139 return false;
1140 }
1141 }
1142 return true;
1143 }
1144
1145protected:
1146 CommandOptions m_options;
1147};
1148
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001149#define SET1 LLDB_OPT_SET_1
1150#define SET2 LLDB_OPT_SET_2
1151
Greg Claytonb3448432011-03-24 21:19:54 +00001152OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +00001153CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
1154{
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001155{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."},
1156{ SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."},
1157{ SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1158{ SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
1159{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001160};
1161
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001162#undef SET1
1163#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +00001164
1165//-------------------------------------------------------------------------
1166// CommandObjectMemory
1167//-------------------------------------------------------------------------
1168
Greg Clayton63094e02010-06-23 01:19:29 +00001169CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001170 CommandObjectMultiword (interpreter,
1171 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001172 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001173 "memory <subcommand> [<subcommand-options>]")
1174{
Greg Clayton238c0a12010-09-18 01:14:36 +00001175 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1176 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001177}
1178
1179CommandObjectMemory::~CommandObjectMemory ()
1180{
1181}