blob: 3336bafec290cf413b483713e235cf49dd555388 [file] [log] [blame]
Chris Lattner30fdc8d2010-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 Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000018#include "lldb/Core/Debugger.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000020#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton66111032010-06-23 01:19:29 +000021#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000023#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000025#include "lldb/Interpreter/OptionGroupFormat.h"
26#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000027#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Sean Callananb6d70eb2011-10-12 02:08:07 +000028#include "lldb/Symbol/ClangNamespaceDecl.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029#include "lldb/Target/Process.h"
Greg Clayton84c39662011-04-27 22:04:39 +000030#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031
32using namespace lldb;
33using namespace lldb_private;
34
Greg Clayton68ebae62011-04-28 20:55:26 +000035static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000036g_option_table[] =
37{
Greg Clayton84c39662011-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 Clayton68ebae62011-04-28 20:55:26 +000050 m_num_per_line (1,1),
Greg Clayton84c39662011-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)
87 error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
88 break;
Greg Clayton1deb7962011-10-25 06:44:01 +000089
Greg Clayton84c39662011-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:
99 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
100 break;
101 }
102 return error;
103 }
104
105 virtual void
106 OptionParsingStarting (CommandInterpreter &interpreter)
107 {
Greg Clayton84c39662011-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 Clayton68ebae62011-04-28 20:55:26 +0000113 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000114 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000115 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000116 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000117 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
118 OptionValueUInt64 &count_value = format_options.GetCountValue();
119 bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000120 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000121 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000122
Greg Clayton1deb7962011-10-25 06:44:01 +0000123 uint32_t format_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000124 if (byte_size_option_set)
125 {
126 if (format_byte_size > 0)
127 {
128 error.SetErrorString("can't specify the byte size in both the '--size <num>' option and the '--format [<byte-size>]<format-char>' options.");
129 return error;
130 }
131 }
132 else
133 {
134 if (format_byte_size != 0)
135 {
136 byte_size_option_set = true;
Greg Clayton1deb7962011-10-25 06:44:01 +0000137 byte_size_value = format_byte_size;
Greg Clayton68ebae62011-04-28 20:55:26 +0000138 }
139 }
140
141 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000142 {
143 default:
144 break;
145
146 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000147 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000148 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000149 if (!num_per_line_option_set)
150 m_num_per_line = 1;
151 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000152 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000153 break;
154
155 case eFormatCString:
156 break;
157
158 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000159 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000160 if (!num_per_line_option_set)
161 m_num_per_line = 4;
162 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000163 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000164 break;
165
166 case eFormatBinary:
167 case eFormatFloat:
168 case eFormatOctal:
169 case eFormatDecimal:
170 case eFormatEnum:
171 case eFormatUnicode16:
172 case eFormatUnicode32:
173 case eFormatUnsigned:
Greg Clayton68ebae62011-04-28 20:55:26 +0000174 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000175 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000176 if (!num_per_line_option_set)
177 m_num_per_line = 1;
178 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000179 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000180 break;
181
182 case eFormatBytes:
183 case eFormatBytesWithASCII:
Greg Clayton1deb7962011-10-25 06:44:01 +0000184 if (byte_size_value.OptionWasSet())
Greg Clayton68ebae62011-04-28 20:55:26 +0000185 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000186 if (byte_size_value > 1)
Greg Clayton68ebae62011-04-28 20:55:26 +0000187 error.SetErrorString ("use --count option to specify an end address to display a number of bytes");
188 }
189 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000190 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000191 if (!num_per_line_option_set)
192 m_num_per_line = 16;
193 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000194 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000195 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000196 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000197 case eFormatChar:
198 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000199 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000200 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000201 if (!num_per_line_option_set)
202 m_num_per_line = 32;
203 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000204 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000205 break;
206 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000207 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000208 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000209 if (!num_per_line_option_set)
210 m_num_per_line = 1;
211 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000212 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000213 break;
214 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000215 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000216 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000217 if (!num_per_line_option_set)
218 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000219 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000220 {
221 case 1:
222 case 2:
223 m_num_per_line = 8;
224 break;
225 case 4:
226 m_num_per_line = 4;
227 break;
228 case 8:
229 m_num_per_line = 2;
230 break;
231 default:
232 m_num_per_line = 1;
233 break;
234 }
235 }
236 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000237 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000238 break;
239
240 case eFormatVectorOfChar:
241 case eFormatVectorOfSInt8:
242 case eFormatVectorOfUInt8:
243 case eFormatVectorOfSInt16:
244 case eFormatVectorOfUInt16:
245 case eFormatVectorOfSInt32:
246 case eFormatVectorOfUInt32:
247 case eFormatVectorOfSInt64:
248 case eFormatVectorOfUInt64:
249 case eFormatVectorOfFloat32:
250 case eFormatVectorOfFloat64:
251 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000252 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000253 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000254 if (!num_per_line_option_set)
255 m_num_per_line = 1;
256 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000257 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000258 break;
259 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000260 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000261 }
262
Greg Clayton84c39662011-04-27 22:04:39 +0000263 OptionValueUInt64 m_num_per_line;
264 bool m_output_as_binary;
265 OptionValueString m_view_as_type;
266};
267
268
269
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000270//----------------------------------------------------------------------
271// Read memory from the inferior process
272//----------------------------------------------------------------------
273class CommandObjectMemoryRead : public CommandObject
274{
275public:
276
Greg Claytona7015092010-09-18 01:14:36 +0000277 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
278 CommandObject (interpreter,
279 "memory read",
Caroline Ticee3d26312010-09-08 21:06:11 +0000280 "Read from the memory of the process being debugged.",
Caroline Tice405fe672010-10-04 22:28:36 +0000281 NULL,
Jim Inghamb8e8a5f2011-07-09 00:55:34 +0000282 eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000283 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000284 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000285 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000286 m_outfile_options (),
287 m_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288 {
Caroline Tice405fe672010-10-04 22:28:36 +0000289 CommandArgumentEntry arg1;
290 CommandArgumentEntry arg2;
291 CommandArgumentData start_addr_arg;
292 CommandArgumentData end_addr_arg;
293
294 // Define the first (and only) variant of this arg.
295 start_addr_arg.arg_type = eArgTypeStartAddress;
296 start_addr_arg.arg_repetition = eArgRepeatPlain;
297
298 // There is only one variant this argument could be; put it into the argument entry.
299 arg1.push_back (start_addr_arg);
300
301 // Define the first (and only) variant of this arg.
302 end_addr_arg.arg_type = eArgTypeEndAddress;
303 end_addr_arg.arg_repetition = eArgRepeatOptional;
304
305 // There is only one variant this argument could be; put it into the argument entry.
306 arg2.push_back (end_addr_arg);
307
308 // Push the data for the first argument into the m_arguments vector.
309 m_arguments.push_back (arg1);
310 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000311
Greg Clayton1deb7962011-10-25 06:44:01 +0000312 // Add the "--format" and "--count" options to group 1 and 3
313 m_option_group.Append (&m_format_options,
314 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
315 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
316 // Add the "--size" option to group 1 and 2
317 m_option_group.Append (&m_format_options,
318 OptionGroupFormat::OPTION_GROUP_SIZE,
319 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000320 m_option_group.Append (&m_memory_options);
321 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton68ebae62011-04-28 20:55:26 +0000322 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000323 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000324 }
325
326 virtual
327 ~CommandObjectMemoryRead ()
328 {
329 }
330
331 Options *
332 GetOptions ()
333 {
Greg Clayton84c39662011-04-27 22:04:39 +0000334 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000335 }
336
337 virtual bool
Greg Claytona7015092010-09-18 01:14:36 +0000338 Execute (Args& command,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000339 CommandReturnObject &result)
340 {
Greg Clayton84c39662011-04-27 22:04:39 +0000341 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Claytonc14ee322011-09-22 04:58:26 +0000342 Target *target = exe_ctx.GetTargetPtr();
343 if (target == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000344 {
Jim Inghamb8e8a5f2011-07-09 00:55:34 +0000345 result.AppendError("need at least a target to read memory");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000346 result.SetStatus(eReturnStatusFailed);
347 return false;
348 }
349 const size_t argc = command.GetArgumentCount();
350
Greg Clayton84c39662011-04-27 22:04:39 +0000351
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000352 if (argc == 0 || argc > 2)
353 {
354 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
355 result.SetStatus(eReturnStatusFailed);
356 return false;
357 }
358
Greg Clayton68ebae62011-04-28 20:55:26 +0000359 ClangASTType clang_ast_type;
360 Error error;
361
362 Format format = m_format_options.GetFormat();
Greg Clayton84c39662011-04-27 22:04:39 +0000363 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
364 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000365 {
Greg Clayton84c39662011-04-27 22:04:39 +0000366 // We are viewing memory as a type
367 SymbolContext sc;
368 const bool append = true;
369 TypeList type_list;
370 uint32_t reference_count = 0;
371 uint32_t pointer_count = 0;
372 size_t idx;
373 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
374 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
375 std::string type_str(view_as_type_cstr);
376
377 // Remove all instances of g_keywords that are followed by spaces
378 for (size_t i = 0; i < g_num_keywords; ++i)
379 {
380 const char *keyword = g_keywords[i];
381 int keyword_len = ::strlen (keyword);
382 while ((idx = type_str.find (keyword)) != std::string::npos)
383 {
384 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
385 type_str.erase(idx, keyword_len+1);
386 }
387 }
388 bool done = type_str.empty();
389 //
390 idx = type_str.find_first_not_of (" \t");
391 if (idx > 0 && idx != std::string::npos)
392 type_str.erase (0, idx);
393 while (!done)
394 {
395 // Strip trailing spaces
396 if (type_str.empty())
397 done = true;
398 else
399 {
400 switch (type_str[type_str.size()-1])
401 {
402 case '*':
403 ++pointer_count;
404 // fall through...
405 case ' ':
406 case '\t':
407 type_str.erase(type_str.size()-1);
408 break;
409
410 case '&':
411 if (reference_count == 0)
412 {
413 reference_count = 1;
414 type_str.erase(type_str.size()-1);
415 }
416 else
417 {
418 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
419 result.SetStatus(eReturnStatusFailed);
420 return false;
421 }
422 break;
423
424 default:
425 done = true;
426 break;
427 }
428 }
429 }
430
431 ConstString lookup_type_name(type_str.c_str());
Greg Claytonc14ee322011-09-22 04:58:26 +0000432 StackFrame *frame = exe_ctx.GetFramePtr();
433 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000434 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000435 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000436 if (sc.module_sp)
437 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000438 sc.module_sp->FindTypes (sc,
439 lookup_type_name,
440 NULL,
Greg Clayton84c39662011-04-27 22:04:39 +0000441 append,
442 1,
443 type_list);
444 }
445 }
446 if (type_list.GetSize() == 0)
447 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000448 target->GetImages().FindTypes (sc,
449 lookup_type_name,
450 append,
451 1,
452 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000453 }
454
455 if (type_list.GetSize() == 0)
456 {
457 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
458 lookup_type_name.GetCString(),
459 view_as_type_cstr);
460 result.SetStatus(eReturnStatusFailed);
461 return false;
462 }
463
464 TypeSP type_sp (type_list.GetTypeAtIndex(0));
465 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
466
467 while (pointer_count > 0)
468 {
469 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
470 if (pointer_type)
471 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
472 else
473 {
474 result.AppendError ("unable make a pointer type\n");
475 result.SetStatus(eReturnStatusFailed);
476 return false;
477 }
478 --pointer_count;
479 }
480
Greg Clayton1deb7962011-10-25 06:44:01 +0000481 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000482
Greg Clayton1deb7962011-10-25 06:44:01 +0000483 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000484 {
485 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
486 view_as_type_cstr);
487 result.SetStatus(eReturnStatusFailed);
488 return false;
489 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000490
Greg Clayton1deb7962011-10-25 06:44:01 +0000491 if (!m_format_options.GetCountValue().OptionWasSet())
492 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000493 }
494 else
495 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000496 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000497 }
498
499 // Look for invalid combinations of settings
500 if (error.Fail())
501 {
502 result.AppendErrorWithFormat("%s", error.AsCString());
503 result.SetStatus(eReturnStatusFailed);
504 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000505 }
506
Greg Clayton1deb7962011-10-25 06:44:01 +0000507 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
508 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000509 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000510
Greg Clayton84c39662011-04-27 22:04:39 +0000511 size_t total_byte_size = item_count * item_byte_size;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000512 if (total_byte_size == 0)
513 total_byte_size = 32;
514
515 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
516
517 if (addr == LLDB_INVALID_ADDRESS)
518 {
519 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
520 result.SetStatus(eReturnStatusFailed);
521 return false;
522 }
523
524 if (argc == 2)
525 {
526 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
527 if (end_addr == LLDB_INVALID_ADDRESS)
528 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000529 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000530 result.SetStatus(eReturnStatusFailed);
531 return false;
532 }
533 else if (end_addr <= addr)
534 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000535 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000536 result.SetStatus(eReturnStatusFailed);
537 return false;
538 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000539 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000540 {
Jason Molendafd54b362011-09-20 21:44:10 +0000541 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000542 result.SetStatus(eReturnStatusFailed);
543 return false;
544 }
545
546 total_byte_size = end_addr - addr;
547 item_count = total_byte_size / item_byte_size;
548 }
Greg Clayton84c39662011-04-27 22:04:39 +0000549
550 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000551 size_t bytes_read = 0;
552 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000553 {
Greg Clayton84c39662011-04-27 22:04:39 +0000554 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Jim Inghamb8e8a5f2011-07-09 00:55:34 +0000555 Address address(NULL, addr);
Greg Claytonc14ee322011-09-22 04:58:26 +0000556 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000557 if (bytes_read == 0)
558 {
559 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
560 result.AppendError(error.AsCString());
561 result.SetStatus(eReturnStatusFailed);
562 return false;
563 }
564
565 if (bytes_read < total_byte_size)
Jason Molendafd54b362011-09-20 21:44:10 +0000566 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000567 }
568
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000569 StreamFile outfile_stream;
570 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000571 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
572 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000573 {
574 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000575 outfile_spec.GetPath (path, sizeof(path));
576
577 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
578 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
579 if (append)
580 open_options |= File::eOpenOptionAppend;
581
582 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000583 {
Greg Clayton84c39662011-04-27 22:04:39 +0000584 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000585 {
586 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
587 if (bytes_written > 0)
588 {
589 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
590 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000591 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000592 path);
593 return true;
594 }
595 else
596 {
597 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
598 result.SetStatus(eReturnStatusFailed);
599 return false;
600 }
601 }
602 else
603 {
604 // We are going to write ASCII to the file just point the
605 // output_stream to our outfile_stream...
606 output_stream = &outfile_stream;
607 }
608 }
609 else
610 {
Greg Clayton84c39662011-04-27 22:04:39 +0000611 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000612 result.SetStatus(eReturnStatusFailed);
613 return false;
614 }
615 }
616 else
617 {
618 output_stream = &result.GetOutputStream();
619 }
620
Greg Clayton84c39662011-04-27 22:04:39 +0000621
622 if (clang_ast_type.GetOpaqueQualType())
623 {
624 for (uint32_t i = 0; i<item_count; ++i)
625 {
626 addr_t item_addr = addr + (i * item_byte_size);
627 Address address (NULL, item_addr);
628 StreamString name_strm;
629 name_strm.Printf ("0x%llx", item_addr);
630 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
631 name_strm.GetString().c_str(),
632 address,
633 clang_ast_type));
634 if (valobj_sp)
635 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000636 if (format != eFormatDefault)
637 valobj_sp->SetFormat (format);
638
Greg Clayton68ebae62011-04-28 20:55:26 +0000639 bool scope_already_checked = true;
Greg Clayton84c39662011-04-27 22:04:39 +0000640
641 ValueObject::DumpValueObject (*output_stream,
642 valobj_sp.get(),
643 NULL,
Greg Clayton68ebae62011-04-28 20:55:26 +0000644 m_varobj_options.ptr_depth,
645 0,
646 m_varobj_options.max_depth,
647 m_varobj_options.show_types,
648 m_varobj_options.show_location,
649 m_varobj_options.use_objc,
Jim Ingham2837b762011-05-04 03:43:18 +0000650 m_varobj_options.use_dynamic,
Enrico Granatace68b022011-08-09 23:50:01 +0000651 m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
Greg Clayton84c39662011-04-27 22:04:39 +0000652 scope_already_checked,
Enrico Granata0c5ef692011-07-16 01:22:04 +0000653 m_varobj_options.flat_output,
Enrico Granata22c55d12011-08-12 02:00:06 +0000654 m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth,
655 m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap);
Greg Clayton84c39662011-04-27 22:04:39 +0000656 }
657 else
658 {
659 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
660 view_as_type_cstr,
661 name_strm.GetString().c_str());
662 result.SetStatus(eReturnStatusFailed);
663 return false;
664 }
665 }
666 return true;
667 }
668
669 result.SetStatus(eReturnStatusSuccessFinishResult);
670 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000671 target->GetArchitecture().GetByteOrder(),
672 target->GetArchitecture().GetAddressByteSize());
Greg Clayton84c39662011-04-27 22:04:39 +0000673
674
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000675 assert (output_stream);
676 data.Dump (output_stream,
677 0,
Greg Clayton84c39662011-04-27 22:04:39 +0000678 m_format_options.GetFormat(),
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000679 item_byte_size,
680 item_count,
681 num_per_line,
682 addr,
683 0,
684 0);
685 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000686 return true;
687 }
688
689protected:
Greg Clayton84c39662011-04-27 22:04:39 +0000690 OptionGroupOptions m_option_group;
691 OptionGroupFormat m_format_options;
692 OptionGroupReadMemory m_memory_options;
693 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000694 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton84c39662011-04-27 22:04:39 +0000695
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000696};
697
Greg Clayton1deb7962011-10-25 06:44:01 +0000698
699OptionDefinition
700g_memory_write_option_table[] =
701{
702{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
703{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
704};
705
706
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000707//----------------------------------------------------------------------
708// Write memory to the inferior process
709//----------------------------------------------------------------------
710class CommandObjectMemoryWrite : public CommandObject
711{
712public:
713
Greg Clayton1deb7962011-10-25 06:44:01 +0000714 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000715 {
716 public:
Greg Clayton1deb7962011-10-25 06:44:01 +0000717 OptionGroupWriteMemory () :
718 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000719 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000720 }
721
722 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +0000723 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000724 {
725 }
726
Greg Clayton1deb7962011-10-25 06:44:01 +0000727 virtual uint32_t
728 GetNumDefinitions ()
729 {
730 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
731 }
732
733 virtual const OptionDefinition*
734 GetDefinitions ()
735 {
736 return g_memory_write_option_table;
737 }
738
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000739 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000740 SetOptionValue (CommandInterpreter &interpreter,
741 uint32_t option_idx,
742 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000743 {
744 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000745 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
746
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000747 switch (short_option)
748 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000749 case 'i':
750 m_infile.SetFile (option_arg, true);
751 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000752 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000753 m_infile.Clear();
754 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000755 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000756 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;
768
769 default:
770 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
771 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000772 }
773 return error;
774 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000775
776 virtual void
777 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000778 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000779 m_infile.Clear();
780 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000781 }
782
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000783 FileSpec m_infile;
784 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000785 };
786
Greg Claytona7015092010-09-18 01:14:36 +0000787 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
788 CommandObject (interpreter,
789 "memory write",
Caroline Ticee3d26312010-09-08 21:06:11 +0000790 "Write to the memory of the process being debugged.",
Caroline Tice405fe672010-10-04 22:28:36 +0000791 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
792 NULL,
Greg Claytoneb0103f2011-04-07 22:46:35 +0000793 eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +0000794 m_option_group (interpreter),
795 m_format_options (eFormatBytes, 1, UINT64_MAX),
796 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000797 {
Caroline Tice405fe672010-10-04 22:28:36 +0000798 CommandArgumentEntry arg1;
799 CommandArgumentEntry arg2;
800 CommandArgumentData addr_arg;
801 CommandArgumentData value_arg;
802
803 // Define the first (and only) variant of this arg.
804 addr_arg.arg_type = eArgTypeAddress;
805 addr_arg.arg_repetition = eArgRepeatPlain;
806
807 // There is only one variant this argument could be; put it into the argument entry.
808 arg1.push_back (addr_arg);
809
810 // Define the first (and only) variant of this arg.
811 value_arg.arg_type = eArgTypeValue;
812 value_arg.arg_repetition = eArgRepeatPlus;
813
814 // There is only one variant this argument could be; put it into the argument entry.
815 arg2.push_back (value_arg);
816
817 // Push the data for the first argument into the m_arguments vector.
818 m_arguments.push_back (arg1);
819 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +0000820
821 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
822 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
823 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
824 m_option_group.Finalize();
825
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000826 }
827
828 virtual
829 ~CommandObjectMemoryWrite ()
830 {
831 }
832
833 Options *
834 GetOptions ()
835 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000836 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000837 }
838
839 bool
840 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
841 {
842 if (total_byte_size > 8)
843 return false;
844
845 if (total_byte_size == 8)
846 return true;
847
848 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
849 return uval64 <= max;
850 }
851
852 bool
853 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
854 {
855 if (total_byte_size > 8)
856 return false;
857
858 if (total_byte_size == 8)
859 return true;
860
861 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
862 const int64_t min = ~(max);
863 return min <= sval64 && sval64 <= max;
864 }
865
866 virtual bool
Greg Claytona7015092010-09-18 01:14:36 +0000867 Execute (Args& command,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000868 CommandReturnObject &result)
869 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000870 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000871 if (process == NULL)
872 {
873 result.AppendError("need a process to read memory");
874 result.SetStatus(eReturnStatusFailed);
875 return false;
876 }
877
878 const size_t argc = command.GetArgumentCount();
879
Greg Clayton1deb7962011-10-25 06:44:01 +0000880 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000881 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000882 if (argc < 1)
883 {
884 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
885 result.SetStatus(eReturnStatusFailed);
886 return false;
887 }
888 }
889 else if (argc < 2)
890 {
891 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000892 result.SetStatus(eReturnStatusFailed);
893 return false;
894 }
895
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000896 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +0000897 process->GetTarget().GetArchitecture().GetAddressByteSize(),
898 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000899
Greg Clayton1deb7962011-10-25 06:44:01 +0000900 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
901 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +0000902
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000903 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
904
905 if (addr == LLDB_INVALID_ADDRESS)
906 {
907 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
908 result.SetStatus(eReturnStatusFailed);
909 return false;
910 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000911
Greg Clayton1deb7962011-10-25 06:44:01 +0000912 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000913 {
914 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +0000915 if (item_byte_size > 0)
916 length = item_byte_size;
917 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000918 if (data_sp)
919 {
920 length = data_sp->GetByteSize();
921 if (length > 0)
922 {
923 Error error;
924 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
925
926 if (bytes_written == length)
927 {
928 // All bytes written
929 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
930 result.SetStatus(eReturnStatusSuccessFinishResult);
931 }
932 else if (bytes_written > 0)
933 {
934 // Some byte written
935 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
936 result.SetStatus(eReturnStatusSuccessFinishResult);
937 }
938 else
939 {
940 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
941 result.SetStatus(eReturnStatusFailed);
942 }
943 }
944 }
945 else
946 {
947 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
948 result.SetStatus(eReturnStatusFailed);
949 }
950 return result.Succeeded();
951 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000952 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000953 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000954 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000955 item_byte_size = buffer.GetAddressByteSize();
956 else
957 item_byte_size = 1;
958 }
959
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000960 command.Shift(); // shift off the address argument
961 uint64_t uval64;
962 int64_t sval64;
963 bool success = false;
964 const uint32_t num_value_args = command.GetArgumentCount();
965 uint32_t i;
966 for (i=0; i<num_value_args; ++i)
967 {
968 const char *value_str = command.GetArgumentAtIndex(i);
969
Greg Clayton1deb7962011-10-25 06:44:01 +0000970 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000971 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +0000972 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000973 case eFormatFloat: // TODO: add support for floats soon
974 case eFormatCharPrintable:
975 case eFormatBytesWithASCII:
976 case eFormatComplex:
977 case eFormatEnum:
978 case eFormatUnicode16:
979 case eFormatUnicode32:
980 case eFormatVectorOfChar:
981 case eFormatVectorOfSInt8:
982 case eFormatVectorOfUInt8:
983 case eFormatVectorOfSInt16:
984 case eFormatVectorOfUInt16:
985 case eFormatVectorOfSInt32:
986 case eFormatVectorOfUInt32:
987 case eFormatVectorOfSInt64:
988 case eFormatVectorOfUInt64:
989 case eFormatVectorOfFloat32:
990 case eFormatVectorOfFloat64:
991 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +0000992 case eFormatOSType:
993 case eFormatComplexInteger:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000994 result.AppendError("unsupported format for writing memory");
995 result.SetStatus(eReturnStatusFailed);
996 return false;
997
998 case eFormatDefault:
999 case eFormatBytes:
1000 case eFormatHex:
Greg Claytonc982c762010-07-09 20:39:50 +00001001 case eFormatPointer:
1002
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001003 // Decode hex bytes
1004 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1005 if (!success)
1006 {
1007 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1008 result.SetStatus(eReturnStatusFailed);
1009 return false;
1010 }
1011 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1012 {
Jason Molendafd54b362011-09-20 21:44:10 +00001013 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001014 result.SetStatus(eReturnStatusFailed);
1015 return false;
1016 }
1017 buffer.PutMaxHex64 (uval64, item_byte_size);
1018 break;
1019
1020 case eFormatBoolean:
1021 uval64 = Args::StringToBoolean(value_str, false, &success);
1022 if (!success)
1023 {
1024 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1025 result.SetStatus(eReturnStatusFailed);
1026 return false;
1027 }
1028 buffer.PutMaxHex64 (uval64, item_byte_size);
1029 break;
1030
1031 case eFormatBinary:
1032 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1033 if (!success)
1034 {
1035 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1036 result.SetStatus(eReturnStatusFailed);
1037 return false;
1038 }
1039 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1040 {
Jason Molendafd54b362011-09-20 21:44:10 +00001041 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001042 result.SetStatus(eReturnStatusFailed);
1043 return false;
1044 }
1045 buffer.PutMaxHex64 (uval64, item_byte_size);
1046 break;
1047
Greg Clayton4e4294b2011-06-17 23:50:44 +00001048 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001049 case eFormatChar:
1050 case eFormatCString:
1051 if (value_str[0])
1052 {
1053 size_t len = strlen (value_str);
1054 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001055 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001056 ++len;
1057 Error error;
1058 if (process->WriteMemory (addr, value_str, len, error) == len)
1059 {
1060 addr += len;
1061 }
1062 else
1063 {
1064 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1065 result.SetStatus(eReturnStatusFailed);
1066 return false;
1067 }
1068 }
1069 break;
1070
1071 case eFormatDecimal:
1072 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1073 if (!success)
1074 {
1075 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1076 result.SetStatus(eReturnStatusFailed);
1077 return false;
1078 }
1079 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1080 {
Jason Molendafd54b362011-09-20 21:44:10 +00001081 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001082 result.SetStatus(eReturnStatusFailed);
1083 return false;
1084 }
1085 buffer.PutMaxHex64 (sval64, item_byte_size);
1086 break;
1087
1088 case eFormatUnsigned:
1089 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1090 if (!success)
1091 {
1092 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1093 result.SetStatus(eReturnStatusFailed);
1094 return false;
1095 }
1096 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1097 {
Jason Molendafd54b362011-09-20 21:44:10 +00001098 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001099 result.SetStatus(eReturnStatusFailed);
1100 return false;
1101 }
1102 buffer.PutMaxHex64 (uval64, item_byte_size);
1103 break;
1104
1105 case eFormatOctal:
1106 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1107 if (!success)
1108 {
1109 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1110 result.SetStatus(eReturnStatusFailed);
1111 return false;
1112 }
1113 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1114 {
Jason Molendafd54b362011-09-20 21:44:10 +00001115 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001116 result.SetStatus(eReturnStatusFailed);
1117 return false;
1118 }
1119 buffer.PutMaxHex64 (uval64, item_byte_size);
1120 break;
1121 }
1122 }
1123
1124 if (!buffer.GetString().empty())
1125 {
1126 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001127 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001128 return true;
1129 else
1130 {
1131 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1132 result.SetStatus(eReturnStatusFailed);
1133 return false;
1134 }
1135 }
1136 return true;
1137 }
1138
1139protected:
Greg Clayton1deb7962011-10-25 06:44:01 +00001140
1141 OptionGroupOptions m_option_group;
1142 OptionGroupFormat m_format_options;
1143 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001144};
1145
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001146
1147//-------------------------------------------------------------------------
1148// CommandObjectMemory
1149//-------------------------------------------------------------------------
1150
Greg Clayton66111032010-06-23 01:19:29 +00001151CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001152 CommandObjectMultiword (interpreter,
1153 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001154 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001155 "memory <subcommand> [<subcommand-options>]")
1156{
Greg Claytona7015092010-09-18 01:14:36 +00001157 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1158 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001159}
1160
1161CommandObjectMemory::~CommandObjectMemory ()
1162{
1163}