blob: 3336bafec290cf413b483713e235cf49dd555388 [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)
87 error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
88 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:
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 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();
119 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 Claytona42880a2011-10-25 06:44:01 +0000123 uint32_t format_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton56bbdaf2011-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 Claytona42880a2011-10-25 06:44:01 +0000137 byte_size_value = format_byte_size;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000138 }
139 }
140
141 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000142 {
143 default:
144 break;
145
146 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000147 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000148 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000149 if (!num_per_line_option_set)
150 m_num_per_line = 1;
151 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000152 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000153 break;
154
155 case eFormatCString:
156 break;
157
158 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000159 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000160 if (!num_per_line_option_set)
161 m_num_per_line = 4;
162 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000163 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000174 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000175 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000176 if (!num_per_line_option_set)
177 m_num_per_line = 1;
178 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000179 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000180 break;
181
182 case eFormatBytes:
183 case eFormatBytesWithASCII:
Greg Claytona42880a2011-10-25 06:44:01 +0000184 if (byte_size_value.OptionWasSet())
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000185 {
Greg Claytona42880a2011-10-25 06:44:01 +0000186 if (byte_size_value > 1)
Greg Clayton56bbdaf2011-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 Claytona42880a2011-10-25 06:44:01 +0000190 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000191 if (!num_per_line_option_set)
192 m_num_per_line = 16;
193 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000194 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000195 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000196 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000197 case eFormatChar:
198 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000199 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000200 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000201 if (!num_per_line_option_set)
202 m_num_per_line = 32;
203 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000204 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000205 break;
206 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000207 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000208 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000209 if (!num_per_line_option_set)
210 m_num_per_line = 1;
211 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000212 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000213 break;
214 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000215 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000216 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000217 if (!num_per_line_option_set)
218 {
Greg Claytona42880a2011-10-25 06:44:01 +0000219 switch (byte_size_value)
Greg Clayton56bbdaf2011-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 Claytona42880a2011-10-25 06:44:01 +0000237 count_value = 8;
Greg Clayton57b3c6b2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000252 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000253 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000254 if (!num_per_line_option_set)
255 m_num_per_line = 1;
256 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000257 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000258 break;
259 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000260 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000261 }
262
Greg Clayton57b3c6b2011-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 Lattner24943d22010-06-08 16:52:24 +0000270//----------------------------------------------------------------------
271// Read memory from the inferior process
272//----------------------------------------------------------------------
273class CommandObjectMemoryRead : public CommandObject
274{
275public:
276
Greg Clayton238c0a12010-09-18 01:14:36 +0000277 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
278 CommandObject (interpreter,
279 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000280 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000281 NULL,
Jim Ingham8cc3f692011-07-09 00:55:34 +0000282 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000283 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000284 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000285 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000286 m_outfile_options (),
287 m_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000288 {
Caroline Tice43b014a2010-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 Clayton57b3c6b2011-04-27 22:04:39 +0000311
Greg Claytona42880a2011-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 Clayton57b3c6b2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000322 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000323 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000324 }
325
326 virtual
327 ~CommandObjectMemoryRead ()
328 {
329 }
330
331 Options *
332 GetOptions ()
333 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000334 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000335 }
336
337 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000338 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000339 CommandReturnObject &result)
340 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000341 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000342 Target *target = exe_ctx.GetTargetPtr();
343 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000344 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000345 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000346 result.SetStatus(eReturnStatusFailed);
347 return false;
348 }
349 const size_t argc = command.GetArgumentCount();
350
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000351
Chris Lattner24943d22010-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 Clayton56bbdaf2011-04-28 20:55:26 +0000359 ClangASTType clang_ast_type;
360 Error error;
361
362 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-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 Lattner24943d22010-06-08 16:52:24 +0000365 {
Greg Clayton57b3c6b2011-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 Clayton567e7f32011-09-22 04:58:26 +0000432 StackFrame *frame = exe_ctx.GetFramePtr();
433 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000434 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000435 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000436 if (sc.module_sp)
437 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000438 sc.module_sp->FindTypes (sc,
439 lookup_type_name,
440 NULL,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000441 append,
442 1,
443 type_list);
444 }
445 }
446 if (type_list.GetSize() == 0)
447 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000448 target->GetImages().FindTypes (sc,
449 lookup_type_name,
450 append,
451 1,
452 type_list);
Greg Clayton57b3c6b2011-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 Claytona42880a2011-10-25 06:44:01 +0000481 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000482
Greg Claytona42880a2011-10-25 06:44:01 +0000483 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000490
Greg Claytona42880a2011-10-25 06:44:01 +0000491 if (!m_format_options.GetCountValue().OptionWasSet())
492 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000493 }
494 else
495 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000496 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-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 Lattner24943d22010-06-08 16:52:24 +0000505 }
506
Greg Claytona42880a2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000509 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000510
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000511 size_t total_byte_size = item_count * item_byte_size;
Chris Lattner24943d22010-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 Clayton56bbdaf2011-04-28 20:55:26 +0000529 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000530 result.SetStatus(eReturnStatusFailed);
531 return false;
532 }
533 else if (end_addr <= addr)
534 {
Greg Clayton56bbdaf2011-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 Lattner24943d22010-06-08 16:52:24 +0000536 result.SetStatus(eReturnStatusFailed);
537 return false;
538 }
Greg Claytona42880a2011-10-25 06:44:01 +0000539 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000540 {
Jason Molenda7e5fa7f2011-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 Lattner24943d22010-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 Clayton57b3c6b2011-04-27 22:04:39 +0000549
550 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000551 size_t bytes_read = 0;
552 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000553 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000554 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Jim Ingham8cc3f692011-07-09 00:55:34 +0000555 Address address(NULL, addr);
Greg Clayton567e7f32011-09-22 04:58:26 +0000556 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-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 Molenda7e5fa7f2011-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 Lattner24943d22010-06-08 16:52:24 +0000567 }
568
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000569 StreamFile outfile_stream;
570 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000571 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
572 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000573 {
574 char path[PATH_MAX];
Greg Clayton57b3c6b2011-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 Claytone9f5fbd2010-10-10 20:52:20 +0000583 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000584 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-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 Clayton57b3c6b2011-04-27 22:04:39 +0000591 append ? "appended" : "written",
Greg Claytone9f5fbd2010-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 Clayton57b3c6b2011-04-27 22:04:39 +0000611 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-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 Clayton57b3c6b2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000636 if (format != eFormatDefault)
637 valobj_sp->SetFormat (format);
638
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000639 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000640
641 ValueObject::DumpValueObject (*output_stream,
642 valobj_sp.get(),
643 NULL,
Greg Clayton56bbdaf2011-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 Ingham10de7d12011-05-04 03:43:18 +0000650 m_varobj_options.use_dynamic,
Enrico Granata840eb262011-08-09 23:50:01 +0000651 m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000652 scope_already_checked,
Enrico Granata7f163b32011-07-16 01:22:04 +0000653 m_varobj_options.flat_output,
Enrico Granata018921d2011-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 Clayton57b3c6b2011-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 Clayton567e7f32011-09-22 04:58:26 +0000671 target->GetArchitecture().GetByteOrder(),
672 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000673
674
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000675 assert (output_stream);
676 data.Dump (output_stream,
677 0,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000678 m_format_options.GetFormat(),
Greg Claytone9f5fbd2010-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 Lattner24943d22010-06-08 16:52:24 +0000686 return true;
687 }
688
689protected:
Greg Clayton57b3c6b2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000694 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000695
Chris Lattner24943d22010-06-08 16:52:24 +0000696};
697
Greg Claytona42880a2011-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 Lattner24943d22010-06-08 16:52:24 +0000707//----------------------------------------------------------------------
708// Write memory to the inferior process
709//----------------------------------------------------------------------
710class CommandObjectMemoryWrite : public CommandObject
711{
712public:
713
Greg Claytona42880a2011-10-25 06:44:01 +0000714 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000715 {
716 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000717 OptionGroupWriteMemory () :
718 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000719 {
Chris Lattner24943d22010-06-08 16:52:24 +0000720 }
721
722 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000723 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000724 {
725 }
726
Greg Claytona42880a2011-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 Lattner24943d22010-06-08 16:52:24 +0000739 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000740 SetOptionValue (CommandInterpreter &interpreter,
741 uint32_t option_idx,
742 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000743 {
744 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000745 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
746
Chris Lattner24943d22010-06-08 16:52:24 +0000747 switch (short_option)
748 {
Greg Claytona42880a2011-10-25 06:44:01 +0000749 case 'i':
750 m_infile.SetFile (option_arg, true);
751 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000752 {
Greg Claytona42880a2011-10-25 06:44:01 +0000753 m_infile.Clear();
754 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000755 }
Greg Claytona42880a2011-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 Lattner24943d22010-06-08 16:52:24 +0000772 }
773 return error;
774 }
Greg Claytona42880a2011-10-25 06:44:01 +0000775
776 virtual void
777 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000778 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000779 m_infile.Clear();
780 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000781 }
782
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000783 FileSpec m_infile;
784 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000785 };
786
Greg Clayton238c0a12010-09-18 01:14:36 +0000787 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
788 CommandObject (interpreter,
789 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000790 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000791 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
792 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000793 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000794 m_option_group (interpreter),
795 m_format_options (eFormatBytes, 1, UINT64_MAX),
796 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000797 {
Caroline Tice43b014a2010-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 Claytona42880a2011-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 Lattner24943d22010-06-08 16:52:24 +0000826 }
827
828 virtual
829 ~CommandObjectMemoryWrite ()
830 {
831 }
832
833 Options *
834 GetOptions ()
835 {
Greg Claytona42880a2011-10-25 06:44:01 +0000836 return &m_option_group;
Chris Lattner24943d22010-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 Clayton238c0a12010-09-18 01:14:36 +0000867 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000868 CommandReturnObject &result)
869 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000870 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-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 Claytona42880a2011-10-25 06:44:01 +0000880 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000881 {
Greg Claytone9f5fbd2010-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 Lattner24943d22010-06-08 16:52:24 +0000892 result.SetStatus(eReturnStatusFailed);
893 return false;
894 }
895
Chris Lattner24943d22010-06-08 16:52:24 +0000896 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000897 process->GetTarget().GetArchitecture().GetAddressByteSize(),
898 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000899
Greg Claytona42880a2011-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 Clayton54e7afa2010-07-09 20:39:50 +0000902
Chris Lattner24943d22010-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 Claytone9f5fbd2010-10-10 20:52:20 +0000911
Greg Claytona42880a2011-10-25 06:44:01 +0000912 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000913 {
914 size_t length = SIZE_MAX;
Greg Claytona42880a2011-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 Claytone9f5fbd2010-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 Claytona42880a2011-10-25 06:44:01 +0000952 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000953 {
Greg Claytona42880a2011-10-25 06:44:01 +0000954 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000955 item_byte_size = buffer.GetAddressByteSize();
956 else
957 item_byte_size = 1;
958 }
959
Chris Lattner24943d22010-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 Claytona42880a2011-10-25 06:44:01 +0000970 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +0000971 {
Greg Clayton3182eff2011-06-23 21:22:24 +0000972 case kNumFormats:
Chris Lattner24943d22010-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 Clayton4fdf7602011-03-20 04:57:14 +0000992 case eFormatOSType:
993 case eFormatComplexInteger:
Chris Lattner24943d22010-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 Clayton54e7afa2010-07-09 20:39:50 +00001001 case eFormatPointer:
1002
Chris Lattner24943d22010-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 Molenda7e5fa7f2011-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 Lattner24943d22010-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 Molenda7e5fa7f2011-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 Lattner24943d22010-06-08 16:52:24 +00001042 result.SetStatus(eReturnStatusFailed);
1043 return false;
1044 }
1045 buffer.PutMaxHex64 (uval64, item_byte_size);
1046 break;
1047
Greg Clayton307fa072011-06-17 23:50:44 +00001048 case eFormatCharArray:
Chris Lattner24943d22010-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 Claytona42880a2011-10-25 06:44:01 +00001055 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-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 Molenda7e5fa7f2011-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 Lattner24943d22010-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 Molenda7e5fa7f2011-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 Lattner24943d22010-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 Molenda7e5fa7f2011-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 Lattner24943d22010-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 Clayton53d68e72010-07-20 22:52:08 +00001127 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-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 Claytona42880a2011-10-25 06:44:01 +00001140
1141 OptionGroupOptions m_option_group;
1142 OptionGroupFormat m_format_options;
1143 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001144};
1145
Chris Lattner24943d22010-06-08 16:52:24 +00001146
1147//-------------------------------------------------------------------------
1148// CommandObjectMemory
1149//-------------------------------------------------------------------------
1150
Greg Clayton63094e02010-06-23 01:19:29 +00001151CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001152 CommandObjectMultiword (interpreter,
1153 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001154 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001155 "memory <subcommand> [<subcommand-options>]")
1156{
Greg Clayton238c0a12010-09-18 01:14:36 +00001157 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1158 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001159}
1160
1161CommandObjectMemory::~CommandObjectMemory ()
1162{
1163}