blob: 85b939cfc364abbbc47b4f1116baa1de2b97bad4 [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"
Chris Lattner24943d22010-06-08 16:52:24 +000028#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000029#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000030
31using namespace lldb;
32using namespace lldb_private;
33
Greg Clayton56bbdaf2011-04-28 20:55:26 +000034static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000035g_option_table[] =
36{
37 { LLDB_OPT_SET_1|
38 LLDB_OPT_SET_2, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize ,"The size in bytes to use when displaying with the selected format."},
39 { LLDB_OPT_SET_1|
40 LLDB_OPT_SET_3, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount ,"The number of total items to display."},
41 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
42 { 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."},
43 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
44};
45
46
47
48class OptionGroupReadMemory : public OptionGroup
49{
50public:
51
52 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000053 m_byte_size (1,1),
54 m_count (8,8),
55 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000056 m_output_as_binary (false),
57 m_view_as_type()
58 {
59 }
60
61 virtual
62 ~OptionGroupReadMemory ()
63 {
64 }
65
66
67 virtual uint32_t
68 GetNumDefinitions ()
69 {
70 return sizeof (g_option_table) / sizeof (OptionDefinition);
71 }
72
73 virtual const OptionDefinition*
74 GetDefinitions ()
75 {
76 return g_option_table;
77 }
78
79 virtual Error
80 SetOptionValue (CommandInterpreter &interpreter,
81 uint32_t option_idx,
82 const char *option_arg)
83 {
84 Error error;
85 char short_option = (char) g_option_table[option_idx].short_option;
86
87 switch (short_option)
88 {
89 case 'l':
90 error = m_num_per_line.SetValueFromCString (option_arg);
91 if (m_num_per_line.GetCurrentValue() == 0)
92 error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
93 break;
94
95 case 'c':
96 error = m_count.SetValueFromCString (option_arg);
97 if (m_count.GetCurrentValue() == 0)
98 error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
99 break;
100
101 case 's':
102 error = m_byte_size.SetValueFromCString (option_arg);
103 if (m_byte_size.GetCurrentValue() == 0)
104 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
105 break;
106
107 case 'b':
108 m_output_as_binary = true;
109 break;
110
111 case 't':
112 error = m_view_as_type.SetValueFromCString (option_arg);
113 break;
114
115 default:
116 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
117 break;
118 }
119 return error;
120 }
121
122 virtual void
123 OptionParsingStarting (CommandInterpreter &interpreter)
124 {
125 m_byte_size.Clear();
126 m_count.Clear();
127 m_num_per_line.Clear();
128 m_output_as_binary = false;
129 m_view_as_type.Clear();
130 }
131
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000132 Error
133 FinalizeSettings (Target *target, const OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000134 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000135 Error error;
136 bool byte_size_option_set = m_byte_size.OptionWasSet();
137 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
138 const bool count_option_set = m_count.OptionWasSet();
139
140 uint32_t format_byte_size = format_options.GetByteSize();
141 if (byte_size_option_set)
142 {
143 if (format_byte_size > 0)
144 {
145 error.SetErrorString("can't specify the byte size in both the '--size <num>' option and the '--format [<byte-size>]<format-char>' options.");
146 return error;
147 }
148 }
149 else
150 {
151 if (format_byte_size != 0)
152 {
153 byte_size_option_set = true;
154 m_byte_size = format_byte_size;
155 }
156 }
157
158 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000159 {
160 default:
161 break;
162
163 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000164 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000165 m_byte_size = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000166 if (!num_per_line_option_set)
167 m_num_per_line = 1;
168 if (!count_option_set)
169 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000170 break;
171
172 case eFormatCString:
173 break;
174
175 case eFormatPointer:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000176 m_byte_size = target->GetArchitecture().GetAddressByteSize();
177 if (!num_per_line_option_set)
178 m_num_per_line = 4;
179 if (!count_option_set)
180 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000181 break;
182
183 case eFormatBinary:
184 case eFormatFloat:
185 case eFormatOctal:
186 case eFormatDecimal:
187 case eFormatEnum:
188 case eFormatUnicode16:
189 case eFormatUnicode32:
190 case eFormatUnsigned:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000191 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000192 m_byte_size = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000193 if (!num_per_line_option_set)
194 m_num_per_line = 1;
195 if (!count_option_set)
196 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000197 break;
198
199 case eFormatBytes:
200 case eFormatBytesWithASCII:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000201 if (m_byte_size.OptionWasSet())
202 {
203 if (m_byte_size > 1)
204 error.SetErrorString ("use --count option to specify an end address to display a number of bytes");
205 }
206 else
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000207 m_byte_size = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000208 if (!num_per_line_option_set)
209 m_num_per_line = 16;
210 if (!count_option_set)
211 m_count = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000212 break;
213 case eFormatChar:
214 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000215 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000216 m_byte_size = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000217 if (!num_per_line_option_set)
218 m_num_per_line = 32;
219 if (!count_option_set)
220 m_count = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000221 break;
222 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000223 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000224 m_byte_size = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000225 if (!num_per_line_option_set)
226 m_num_per_line = 1;
227 if (!count_option_set)
228 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000229 break;
230 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000231 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000232 m_byte_size = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000233 if (!num_per_line_option_set)
234 {
235 switch (m_byte_size)
236 {
237 case 1:
238 case 2:
239 m_num_per_line = 8;
240 break;
241 case 4:
242 m_num_per_line = 4;
243 break;
244 case 8:
245 m_num_per_line = 2;
246 break;
247 default:
248 m_num_per_line = 1;
249 break;
250 }
251 }
252 if (!count_option_set)
253 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000254 break;
255
256 case eFormatVectorOfChar:
257 case eFormatVectorOfSInt8:
258 case eFormatVectorOfUInt8:
259 case eFormatVectorOfSInt16:
260 case eFormatVectorOfUInt16:
261 case eFormatVectorOfSInt32:
262 case eFormatVectorOfUInt32:
263 case eFormatVectorOfSInt64:
264 case eFormatVectorOfUInt64:
265 case eFormatVectorOfFloat32:
266 case eFormatVectorOfFloat64:
267 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000268 if (!byte_size_option_set)
269 m_byte_size = 128;
270 if (!num_per_line_option_set)
271 m_num_per_line = 1;
272 if (!count_option_set)
273 m_count = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000274 break;
275 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000276 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000277 }
278
279 OptionValueUInt64 m_byte_size;
280 OptionValueUInt64 m_count;
281 OptionValueUInt64 m_num_per_line;
282 bool m_output_as_binary;
283 OptionValueString m_view_as_type;
284};
285
286
287
Chris Lattner24943d22010-06-08 16:52:24 +0000288//----------------------------------------------------------------------
289// Read memory from the inferior process
290//----------------------------------------------------------------------
291class CommandObjectMemoryRead : public CommandObject
292{
293public:
294
Greg Clayton238c0a12010-09-18 01:14:36 +0000295 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
296 CommandObject (interpreter,
297 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000298 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000299 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000300 eFlagProcessMustBeLaunched),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000301 m_option_group (interpreter),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000302 m_format_options (eFormatBytesWithASCII, 0, true),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000303 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000304 m_outfile_options (),
305 m_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000306 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000307 CommandArgumentEntry arg1;
308 CommandArgumentEntry arg2;
309 CommandArgumentData start_addr_arg;
310 CommandArgumentData end_addr_arg;
311
312 // Define the first (and only) variant of this arg.
313 start_addr_arg.arg_type = eArgTypeStartAddress;
314 start_addr_arg.arg_repetition = eArgRepeatPlain;
315
316 // There is only one variant this argument could be; put it into the argument entry.
317 arg1.push_back (start_addr_arg);
318
319 // Define the first (and only) variant of this arg.
320 end_addr_arg.arg_type = eArgTypeEndAddress;
321 end_addr_arg.arg_repetition = eArgRepeatOptional;
322
323 // There is only one variant this argument could be; put it into the argument entry.
324 arg2.push_back (end_addr_arg);
325
326 // Push the data for the first argument into the m_arguments vector.
327 m_arguments.push_back (arg1);
328 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000329
330 m_option_group.Append (&m_format_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
331 m_option_group.Append (&m_memory_options);
332 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 +0000333 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000334 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000335 }
336
337 virtual
338 ~CommandObjectMemoryRead ()
339 {
340 }
341
342 Options *
343 GetOptions ()
344 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000345 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000346 }
347
348 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000349 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000350 CommandReturnObject &result)
351 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000352 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
353 if (exe_ctx.process == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000354 {
355 result.AppendError("need a process to read memory");
356 result.SetStatus(eReturnStatusFailed);
357 return false;
358 }
359 const size_t argc = command.GetArgumentCount();
360
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000361
Chris Lattner24943d22010-06-08 16:52:24 +0000362 if (argc == 0 || argc > 2)
363 {
364 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
365 result.SetStatus(eReturnStatusFailed);
366 return false;
367 }
368
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000369 ClangASTType clang_ast_type;
370 Error error;
371
372 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000373 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
374 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000375 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000376 // We are viewing memory as a type
377 SymbolContext sc;
378 const bool append = true;
379 TypeList type_list;
380 uint32_t reference_count = 0;
381 uint32_t pointer_count = 0;
382 size_t idx;
383 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
384 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
385 std::string type_str(view_as_type_cstr);
386
387 // Remove all instances of g_keywords that are followed by spaces
388 for (size_t i = 0; i < g_num_keywords; ++i)
389 {
390 const char *keyword = g_keywords[i];
391 int keyword_len = ::strlen (keyword);
392 while ((idx = type_str.find (keyword)) != std::string::npos)
393 {
394 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
395 type_str.erase(idx, keyword_len+1);
396 }
397 }
398 bool done = type_str.empty();
399 //
400 idx = type_str.find_first_not_of (" \t");
401 if (idx > 0 && idx != std::string::npos)
402 type_str.erase (0, idx);
403 while (!done)
404 {
405 // Strip trailing spaces
406 if (type_str.empty())
407 done = true;
408 else
409 {
410 switch (type_str[type_str.size()-1])
411 {
412 case '*':
413 ++pointer_count;
414 // fall through...
415 case ' ':
416 case '\t':
417 type_str.erase(type_str.size()-1);
418 break;
419
420 case '&':
421 if (reference_count == 0)
422 {
423 reference_count = 1;
424 type_str.erase(type_str.size()-1);
425 }
426 else
427 {
428 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
429 result.SetStatus(eReturnStatusFailed);
430 return false;
431 }
432 break;
433
434 default:
435 done = true;
436 break;
437 }
438 }
439 }
440
441 ConstString lookup_type_name(type_str.c_str());
442 if (exe_ctx.frame)
443 {
444 sc = exe_ctx.frame->GetSymbolContext (eSymbolContextModule);
445 if (sc.module_sp)
446 {
447 sc.module_sp->FindTypes (sc,
448 lookup_type_name,
449 append,
450 1,
451 type_list);
452 }
453 }
454 if (type_list.GetSize() == 0)
455 {
456 exe_ctx.target->GetImages().FindTypes (sc,
457 lookup_type_name,
458 append,
459 1,
460 type_list);
461 }
462
463 if (type_list.GetSize() == 0)
464 {
465 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
466 lookup_type_name.GetCString(),
467 view_as_type_cstr);
468 result.SetStatus(eReturnStatusFailed);
469 return false;
470 }
471
472 TypeSP type_sp (type_list.GetTypeAtIndex(0));
473 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
474
475 while (pointer_count > 0)
476 {
477 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
478 if (pointer_type)
479 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
480 else
481 {
482 result.AppendError ("unable make a pointer type\n");
483 result.SetStatus(eReturnStatusFailed);
484 return false;
485 }
486 --pointer_count;
487 }
488
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000489 m_memory_options.m_byte_size = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000490
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000491 if (m_memory_options.m_byte_size == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000492 {
493 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
494 view_as_type_cstr);
495 result.SetStatus(eReturnStatusFailed);
496 return false;
497 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000498
499 if (!m_memory_options.m_count.OptionWasSet())
500 m_memory_options.m_count = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000501 }
502 else
503 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000504 error = m_memory_options.FinalizeSettings (exe_ctx.target, m_format_options);
505 }
506
507 // Look for invalid combinations of settings
508 if (error.Fail())
509 {
510 result.AppendErrorWithFormat("%s", error.AsCString());
511 result.SetStatus(eReturnStatusFailed);
512 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000513 }
514
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000515 size_t item_count = m_memory_options.m_count.GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000516 const size_t item_byte_size = m_memory_options.m_byte_size;
517 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000518
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000519 size_t total_byte_size = item_count * item_byte_size;
Chris Lattner24943d22010-06-08 16:52:24 +0000520 if (total_byte_size == 0)
521 total_byte_size = 32;
522
523 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
524
525 if (addr == LLDB_INVALID_ADDRESS)
526 {
527 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
528 result.SetStatus(eReturnStatusFailed);
529 return false;
530 }
531
532 if (argc == 2)
533 {
534 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
535 if (end_addr == LLDB_INVALID_ADDRESS)
536 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000537 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000538 result.SetStatus(eReturnStatusFailed);
539 return false;
540 }
541 else if (end_addr <= addr)
542 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000543 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 +0000544 result.SetStatus(eReturnStatusFailed);
545 return false;
546 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000547 else if (m_memory_options.m_count.OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000548 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000549 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
Chris Lattner24943d22010-06-08 16:52:24 +0000550 result.SetStatus(eReturnStatusFailed);
551 return false;
552 }
553
554 total_byte_size = end_addr - addr;
555 item_count = total_byte_size / item_byte_size;
556 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000557
558 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000559 size_t bytes_read = 0;
560 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000561 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000562 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
563 bytes_read = exe_ctx.process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
564 if (bytes_read == 0)
565 {
566 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
567 result.AppendError(error.AsCString());
568 result.SetStatus(eReturnStatusFailed);
569 return false;
570 }
571
572 if (bytes_read < total_byte_size)
573 result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
Chris Lattner24943d22010-06-08 16:52:24 +0000574 }
575
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000576 StreamFile outfile_stream;
577 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000578 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
579 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000580 {
581 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000582 outfile_spec.GetPath (path, sizeof(path));
583
584 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
585 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
586 if (append)
587 open_options |= File::eOpenOptionAppend;
588
589 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000590 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000591 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000592 {
593 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
594 if (bytes_written > 0)
595 {
596 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
597 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000598 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000599 path);
600 return true;
601 }
602 else
603 {
604 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
605 result.SetStatus(eReturnStatusFailed);
606 return false;
607 }
608 }
609 else
610 {
611 // We are going to write ASCII to the file just point the
612 // output_stream to our outfile_stream...
613 output_stream = &outfile_stream;
614 }
615 }
616 else
617 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000618 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000619 result.SetStatus(eReturnStatusFailed);
620 return false;
621 }
622 }
623 else
624 {
625 output_stream = &result.GetOutputStream();
626 }
627
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000628
629 if (clang_ast_type.GetOpaqueQualType())
630 {
631 for (uint32_t i = 0; i<item_count; ++i)
632 {
633 addr_t item_addr = addr + (i * item_byte_size);
634 Address address (NULL, item_addr);
635 StreamString name_strm;
636 name_strm.Printf ("0x%llx", item_addr);
637 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
638 name_strm.GetString().c_str(),
639 address,
640 clang_ast_type));
641 if (valobj_sp)
642 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000643 if (format != eFormatDefault)
644 valobj_sp->SetFormat (format);
645
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000646 bool use_dynamic = false;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000647 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000648
649 ValueObject::DumpValueObject (*output_stream,
650 valobj_sp.get(),
651 NULL,
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000652 m_varobj_options.ptr_depth,
653 0,
654 m_varobj_options.max_depth,
655 m_varobj_options.show_types,
656 m_varobj_options.show_location,
657 m_varobj_options.use_objc,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000658 use_dynamic,
659 scope_already_checked,
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000660 m_varobj_options.flat_output);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000661 }
662 else
663 {
664 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
665 view_as_type_cstr,
666 name_strm.GetString().c_str());
667 result.SetStatus(eReturnStatusFailed);
668 return false;
669 }
670 }
671 return true;
672 }
673
674 result.SetStatus(eReturnStatusSuccessFinishResult);
675 DataExtractor data (data_sp,
676 exe_ctx.target->GetArchitecture().GetByteOrder(),
677 exe_ctx.target->GetArchitecture().GetAddressByteSize());
678
679
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000680 assert (output_stream);
681 data.Dump (output_stream,
682 0,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000683 m_format_options.GetFormat(),
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000684 item_byte_size,
685 item_count,
686 num_per_line,
687 addr,
688 0,
689 0);
690 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000691 return true;
692 }
693
694protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000695// CommandOptions m_options;
696 OptionGroupOptions m_option_group;
697 OptionGroupFormat m_format_options;
698 OptionGroupReadMemory m_memory_options;
699 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000700 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000701
Chris Lattner24943d22010-06-08 16:52:24 +0000702};
703
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000704//OptionDefinition
705//CommandObjectMemoryRead::CommandOptions::g_option_table[] =
706//{
707//{ LLDB_OPT_SET_1, false, "format" ,'f', required_argument, NULL, 0, eArgTypeFormat ,"The format that will be used to display the memory. Defaults to bytes with ASCII (--format=Y)."},
708//{ LLDB_OPT_SET_1, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize ,"The size in bytes to use when displaying with the selected format."},
709//{ LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
710//{ LLDB_OPT_SET_1|
711// LLDB_OPT_SET_2|
712// LLDB_OPT_SET_3, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount ,"The number of total items to display."},
713//{ LLDB_OPT_SET_1|
714// LLDB_OPT_SET_2|
715// LLDB_OPT_SET_3, false, "outfile" ,'o', required_argument, NULL, 0, eArgTypeFilename ,"Dump memory read results into a file."},
716//{ LLDB_OPT_SET_1|
717// LLDB_OPT_SET_2|
718// LLDB_OPT_SET_3, false, "append" ,'a', no_argument , NULL, 0, eArgTypeNone ,"Append memory read results to 'outfile'."},
719//{ 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."},
720//{ LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
721//{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
722//};
Chris Lattner24943d22010-06-08 16:52:24 +0000723
724//----------------------------------------------------------------------
725// Write memory to the inferior process
726//----------------------------------------------------------------------
727class CommandObjectMemoryWrite : public CommandObject
728{
729public:
730
731 class CommandOptions : public Options
732 {
733 public:
Greg Claytonf15996e2011-04-07 22:46:35 +0000734 CommandOptions (CommandInterpreter &interpreter) :
735 Options(interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000736 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000737 OptionParsingStarting();
Chris Lattner24943d22010-06-08 16:52:24 +0000738 }
739
740 virtual
741 ~CommandOptions ()
742 {
743 }
744
745 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000746 SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000747 {
748 Error error;
749 char short_option = (char) m_getopt_table[option_idx].val;
750 switch (short_option)
751 {
752 case 'f':
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000753 error = Args::StringToFormat (option_arg, m_format, &m_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +0000754 break;
755
756 case 's':
757 m_byte_size = Args::StringToUInt32 (option_arg, 0);
758 if (m_byte_size == 0)
759 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
760 break;
761
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000762 case 'i':
Greg Clayton537a7a82010-10-20 20:54:39 +0000763 m_infile.SetFile (option_arg, true);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000764 if (!m_infile.Exists())
765 {
766 m_infile.Clear();
767 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg);
768 }
769 break;
770
771 case 'o':
772 {
773 bool success;
774 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
775 if (!success)
776 {
777 error.SetErrorStringWithFormat("Invalid offset string '%s'\n", option_arg);
778 }
779 }
780 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000781
782 default:
783 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
784 break;
785 }
786 return error;
787 }
788
789 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000790 OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000791 {
Chris Lattner24943d22010-06-08 16:52:24 +0000792 m_format = eFormatBytes;
793 m_byte_size = 1;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000794 m_infile.Clear();
795 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000796 }
797
Greg Claytonb3448432011-03-24 21:19:54 +0000798 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000799 GetDefinitions ()
800 {
801 return g_option_table;
802 }
803
804 // Options table: Required for subclasses of Options.
805
Greg Claytonb3448432011-03-24 21:19:54 +0000806 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000807
808 // Instance variables to hold the values for command options.
809 lldb::Format m_format;
810 uint32_t m_byte_size;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000811 FileSpec m_infile;
812 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000813 };
814
Greg Clayton238c0a12010-09-18 01:14:36 +0000815 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
816 CommandObject (interpreter,
817 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000818 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000819 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
820 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000821 eFlagProcessMustBeLaunched),
822 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000823 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000824 CommandArgumentEntry arg1;
825 CommandArgumentEntry arg2;
826 CommandArgumentData addr_arg;
827 CommandArgumentData value_arg;
828
829 // Define the first (and only) variant of this arg.
830 addr_arg.arg_type = eArgTypeAddress;
831 addr_arg.arg_repetition = eArgRepeatPlain;
832
833 // There is only one variant this argument could be; put it into the argument entry.
834 arg1.push_back (addr_arg);
835
836 // Define the first (and only) variant of this arg.
837 value_arg.arg_type = eArgTypeValue;
838 value_arg.arg_repetition = eArgRepeatPlus;
839
840 // There is only one variant this argument could be; put it into the argument entry.
841 arg2.push_back (value_arg);
842
843 // Push the data for the first argument into the m_arguments vector.
844 m_arguments.push_back (arg1);
845 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000846 }
847
848 virtual
849 ~CommandObjectMemoryWrite ()
850 {
851 }
852
853 Options *
854 GetOptions ()
855 {
856 return &m_options;
857 }
858
859 bool
860 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
861 {
862 if (total_byte_size > 8)
863 return false;
864
865 if (total_byte_size == 8)
866 return true;
867
868 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
869 return uval64 <= max;
870 }
871
872 bool
873 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
874 {
875 if (total_byte_size > 8)
876 return false;
877
878 if (total_byte_size == 8)
879 return true;
880
881 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
882 const int64_t min = ~(max);
883 return min <= sval64 && sval64 <= max;
884 }
885
886 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000887 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000888 CommandReturnObject &result)
889 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000890 Process *process = m_interpreter.GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000891 if (process == NULL)
892 {
893 result.AppendError("need a process to read memory");
894 result.SetStatus(eReturnStatusFailed);
895 return false;
896 }
897
898 const size_t argc = command.GetArgumentCount();
899
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000900 if (m_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000901 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000902 if (argc < 1)
903 {
904 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
905 result.SetStatus(eReturnStatusFailed);
906 return false;
907 }
908 }
909 else if (argc < 2)
910 {
911 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 +0000912 result.SetStatus(eReturnStatusFailed);
913 return false;
914 }
915
Chris Lattner24943d22010-06-08 16:52:24 +0000916 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000917 process->GetTarget().GetArchitecture().GetAddressByteSize(),
918 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000919
Greg Clayton54e7afa2010-07-09 20:39:50 +0000920 size_t item_byte_size = m_options.m_byte_size;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000921
Chris Lattner24943d22010-06-08 16:52:24 +0000922 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
923
924 if (addr == LLDB_INVALID_ADDRESS)
925 {
926 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
927 result.SetStatus(eReturnStatusFailed);
928 return false;
929 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000930
931 if (m_options.m_infile)
932 {
933 size_t length = SIZE_MAX;
934 if (m_options.m_byte_size > 0)
935 length = m_options.m_byte_size;
936 lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length));
937 if (data_sp)
938 {
939 length = data_sp->GetByteSize();
940 if (length > 0)
941 {
942 Error error;
943 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
944
945 if (bytes_written == length)
946 {
947 // All bytes written
948 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
949 result.SetStatus(eReturnStatusSuccessFinishResult);
950 }
951 else if (bytes_written > 0)
952 {
953 // Some byte written
954 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
955 result.SetStatus(eReturnStatusSuccessFinishResult);
956 }
957 else
958 {
959 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
960 result.SetStatus(eReturnStatusFailed);
961 }
962 }
963 }
964 else
965 {
966 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
967 result.SetStatus(eReturnStatusFailed);
968 }
969 return result.Succeeded();
970 }
971 else if (m_options.m_byte_size == 0)
972 {
973 if (m_options.m_format == eFormatPointer)
974 item_byte_size = buffer.GetAddressByteSize();
975 else
976 item_byte_size = 1;
977 }
978
Chris Lattner24943d22010-06-08 16:52:24 +0000979 command.Shift(); // shift off the address argument
980 uint64_t uval64;
981 int64_t sval64;
982 bool success = false;
983 const uint32_t num_value_args = command.GetArgumentCount();
984 uint32_t i;
985 for (i=0; i<num_value_args; ++i)
986 {
987 const char *value_str = command.GetArgumentAtIndex(i);
988
989 switch (m_options.m_format)
990 {
991 case eFormatFloat: // TODO: add support for floats soon
992 case eFormatCharPrintable:
993 case eFormatBytesWithASCII:
994 case eFormatComplex:
995 case eFormatEnum:
996 case eFormatUnicode16:
997 case eFormatUnicode32:
998 case eFormatVectorOfChar:
999 case eFormatVectorOfSInt8:
1000 case eFormatVectorOfUInt8:
1001 case eFormatVectorOfSInt16:
1002 case eFormatVectorOfUInt16:
1003 case eFormatVectorOfSInt32:
1004 case eFormatVectorOfUInt32:
1005 case eFormatVectorOfSInt64:
1006 case eFormatVectorOfUInt64:
1007 case eFormatVectorOfFloat32:
1008 case eFormatVectorOfFloat64:
1009 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001010 case eFormatOSType:
1011 case eFormatComplexInteger:
Chris Lattner24943d22010-06-08 16:52:24 +00001012 result.AppendError("unsupported format for writing memory");
1013 result.SetStatus(eReturnStatusFailed);
1014 return false;
1015
1016 case eFormatDefault:
1017 case eFormatBytes:
1018 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001019 case eFormatPointer:
1020
Chris Lattner24943d22010-06-08 16:52:24 +00001021 // Decode hex bytes
1022 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1023 if (!success)
1024 {
1025 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1026 result.SetStatus(eReturnStatusFailed);
1027 return false;
1028 }
1029 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1030 {
1031 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1032 result.SetStatus(eReturnStatusFailed);
1033 return false;
1034 }
1035 buffer.PutMaxHex64 (uval64, item_byte_size);
1036 break;
1037
1038 case eFormatBoolean:
1039 uval64 = Args::StringToBoolean(value_str, false, &success);
1040 if (!success)
1041 {
1042 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1043 result.SetStatus(eReturnStatusFailed);
1044 return false;
1045 }
1046 buffer.PutMaxHex64 (uval64, item_byte_size);
1047 break;
1048
1049 case eFormatBinary:
1050 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1051 if (!success)
1052 {
1053 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1054 result.SetStatus(eReturnStatusFailed);
1055 return false;
1056 }
1057 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1058 {
1059 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1060 result.SetStatus(eReturnStatusFailed);
1061 return false;
1062 }
1063 buffer.PutMaxHex64 (uval64, item_byte_size);
1064 break;
1065
1066 case eFormatChar:
1067 case eFormatCString:
1068 if (value_str[0])
1069 {
1070 size_t len = strlen (value_str);
1071 // Include the NULL for C strings...
1072 if (m_options.m_format == eFormatCString)
1073 ++len;
1074 Error error;
1075 if (process->WriteMemory (addr, value_str, len, error) == len)
1076 {
1077 addr += len;
1078 }
1079 else
1080 {
1081 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1082 result.SetStatus(eReturnStatusFailed);
1083 return false;
1084 }
1085 }
1086 break;
1087
1088 case eFormatDecimal:
1089 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1090 if (!success)
1091 {
1092 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1093 result.SetStatus(eReturnStatusFailed);
1094 return false;
1095 }
1096 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1097 {
1098 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
1099 result.SetStatus(eReturnStatusFailed);
1100 return false;
1101 }
1102 buffer.PutMaxHex64 (sval64, item_byte_size);
1103 break;
1104
1105 case eFormatUnsigned:
1106 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1107 if (!success)
1108 {
1109 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1110 result.SetStatus(eReturnStatusFailed);
1111 return false;
1112 }
1113 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1114 {
1115 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1116 result.SetStatus(eReturnStatusFailed);
1117 return false;
1118 }
1119 buffer.PutMaxHex64 (uval64, item_byte_size);
1120 break;
1121
1122 case eFormatOctal:
1123 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1124 if (!success)
1125 {
1126 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1127 result.SetStatus(eReturnStatusFailed);
1128 return false;
1129 }
1130 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1131 {
1132 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1133 result.SetStatus(eReturnStatusFailed);
1134 return false;
1135 }
1136 buffer.PutMaxHex64 (uval64, item_byte_size);
1137 break;
1138 }
1139 }
1140
1141 if (!buffer.GetString().empty())
1142 {
1143 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001144 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001145 return true;
1146 else
1147 {
1148 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1149 result.SetStatus(eReturnStatusFailed);
1150 return false;
1151 }
1152 }
1153 return true;
1154 }
1155
1156protected:
1157 CommandOptions m_options;
1158};
1159
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001160#define SET1 LLDB_OPT_SET_1
1161#define SET2 LLDB_OPT_SET_2
1162
Greg Claytonb3448432011-03-24 21:19:54 +00001163OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +00001164CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
1165{
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001166{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."},
1167{ SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."},
1168{ SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1169{ SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
1170{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001171};
1172
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001173#undef SET1
1174#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +00001175
1176//-------------------------------------------------------------------------
1177// CommandObjectMemory
1178//-------------------------------------------------------------------------
1179
Greg Clayton63094e02010-06-23 01:19:29 +00001180CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001181 CommandObjectMultiword (interpreter,
1182 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001183 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001184 "memory <subcommand> [<subcommand-options>]")
1185{
Greg Clayton238c0a12010-09-18 01:14:36 +00001186 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1187 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001188}
1189
1190CommandObjectMemory::~CommandObjectMemory ()
1191{
1192}