blob: 6bdd40bdfd027bb23be985e1dd2d5124c0d2e15d [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;
Greg Clayton307fa072011-06-17 23:50:44 +0000213 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000214 case eFormatChar:
215 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000216 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000217 m_byte_size = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000218 if (!num_per_line_option_set)
219 m_num_per_line = 32;
220 if (!count_option_set)
221 m_count = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000222 break;
223 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000224 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000225 m_byte_size = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000226 if (!num_per_line_option_set)
227 m_num_per_line = 1;
228 if (!count_option_set)
229 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000230 break;
231 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000232 if (!byte_size_option_set)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000233 m_byte_size = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000234 if (!num_per_line_option_set)
235 {
236 switch (m_byte_size)
237 {
238 case 1:
239 case 2:
240 m_num_per_line = 8;
241 break;
242 case 4:
243 m_num_per_line = 4;
244 break;
245 case 8:
246 m_num_per_line = 2;
247 break;
248 default:
249 m_num_per_line = 1;
250 break;
251 }
252 }
253 if (!count_option_set)
254 m_count = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000255 break;
256
257 case eFormatVectorOfChar:
258 case eFormatVectorOfSInt8:
259 case eFormatVectorOfUInt8:
260 case eFormatVectorOfSInt16:
261 case eFormatVectorOfUInt16:
262 case eFormatVectorOfSInt32:
263 case eFormatVectorOfUInt32:
264 case eFormatVectorOfSInt64:
265 case eFormatVectorOfUInt64:
266 case eFormatVectorOfFloat32:
267 case eFormatVectorOfFloat64:
268 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000269 if (!byte_size_option_set)
270 m_byte_size = 128;
271 if (!num_per_line_option_set)
272 m_num_per_line = 1;
273 if (!count_option_set)
274 m_count = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000275 break;
276 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000277 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000278 }
279
280 OptionValueUInt64 m_byte_size;
281 OptionValueUInt64 m_count;
282 OptionValueUInt64 m_num_per_line;
283 bool m_output_as_binary;
284 OptionValueString m_view_as_type;
285};
286
287
288
Chris Lattner24943d22010-06-08 16:52:24 +0000289//----------------------------------------------------------------------
290// Read memory from the inferior process
291//----------------------------------------------------------------------
292class CommandObjectMemoryRead : public CommandObject
293{
294public:
295
Greg Clayton238c0a12010-09-18 01:14:36 +0000296 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
297 CommandObject (interpreter,
298 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000299 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000300 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000301 eFlagProcessMustBeLaunched),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000302 m_option_group (interpreter),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000303 m_format_options (eFormatBytesWithASCII, 0, true),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000304 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000305 m_outfile_options (),
306 m_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000307 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000308 CommandArgumentEntry arg1;
309 CommandArgumentEntry arg2;
310 CommandArgumentData start_addr_arg;
311 CommandArgumentData end_addr_arg;
312
313 // Define the first (and only) variant of this arg.
314 start_addr_arg.arg_type = eArgTypeStartAddress;
315 start_addr_arg.arg_repetition = eArgRepeatPlain;
316
317 // There is only one variant this argument could be; put it into the argument entry.
318 arg1.push_back (start_addr_arg);
319
320 // Define the first (and only) variant of this arg.
321 end_addr_arg.arg_type = eArgTypeEndAddress;
322 end_addr_arg.arg_repetition = eArgRepeatOptional;
323
324 // There is only one variant this argument could be; put it into the argument entry.
325 arg2.push_back (end_addr_arg);
326
327 // Push the data for the first argument into the m_arguments vector.
328 m_arguments.push_back (arg1);
329 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000330
331 m_option_group.Append (&m_format_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
332 m_option_group.Append (&m_memory_options);
333 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 +0000334 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000335 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000336 }
337
338 virtual
339 ~CommandObjectMemoryRead ()
340 {
341 }
342
343 Options *
344 GetOptions ()
345 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000346 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000347 }
348
349 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000350 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000351 CommandReturnObject &result)
352 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000353 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
354 if (exe_ctx.process == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000355 {
356 result.AppendError("need a process to read memory");
357 result.SetStatus(eReturnStatusFailed);
358 return false;
359 }
360 const size_t argc = command.GetArgumentCount();
361
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000362
Chris Lattner24943d22010-06-08 16:52:24 +0000363 if (argc == 0 || argc > 2)
364 {
365 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
366 result.SetStatus(eReturnStatusFailed);
367 return false;
368 }
369
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000370 ClangASTType clang_ast_type;
371 Error error;
372
373 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000374 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
375 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000376 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000377 // We are viewing memory as a type
378 SymbolContext sc;
379 const bool append = true;
380 TypeList type_list;
381 uint32_t reference_count = 0;
382 uint32_t pointer_count = 0;
383 size_t idx;
384 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
385 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
386 std::string type_str(view_as_type_cstr);
387
388 // Remove all instances of g_keywords that are followed by spaces
389 for (size_t i = 0; i < g_num_keywords; ++i)
390 {
391 const char *keyword = g_keywords[i];
392 int keyword_len = ::strlen (keyword);
393 while ((idx = type_str.find (keyword)) != std::string::npos)
394 {
395 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
396 type_str.erase(idx, keyword_len+1);
397 }
398 }
399 bool done = type_str.empty();
400 //
401 idx = type_str.find_first_not_of (" \t");
402 if (idx > 0 && idx != std::string::npos)
403 type_str.erase (0, idx);
404 while (!done)
405 {
406 // Strip trailing spaces
407 if (type_str.empty())
408 done = true;
409 else
410 {
411 switch (type_str[type_str.size()-1])
412 {
413 case '*':
414 ++pointer_count;
415 // fall through...
416 case ' ':
417 case '\t':
418 type_str.erase(type_str.size()-1);
419 break;
420
421 case '&':
422 if (reference_count == 0)
423 {
424 reference_count = 1;
425 type_str.erase(type_str.size()-1);
426 }
427 else
428 {
429 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
430 result.SetStatus(eReturnStatusFailed);
431 return false;
432 }
433 break;
434
435 default:
436 done = true;
437 break;
438 }
439 }
440 }
441
442 ConstString lookup_type_name(type_str.c_str());
443 if (exe_ctx.frame)
444 {
445 sc = exe_ctx.frame->GetSymbolContext (eSymbolContextModule);
446 if (sc.module_sp)
447 {
448 sc.module_sp->FindTypes (sc,
449 lookup_type_name,
450 append,
451 1,
452 type_list);
453 }
454 }
455 if (type_list.GetSize() == 0)
456 {
457 exe_ctx.target->GetImages().FindTypes (sc,
458 lookup_type_name,
459 append,
460 1,
461 type_list);
462 }
463
464 if (type_list.GetSize() == 0)
465 {
466 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
467 lookup_type_name.GetCString(),
468 view_as_type_cstr);
469 result.SetStatus(eReturnStatusFailed);
470 return false;
471 }
472
473 TypeSP type_sp (type_list.GetTypeAtIndex(0));
474 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
475
476 while (pointer_count > 0)
477 {
478 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
479 if (pointer_type)
480 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
481 else
482 {
483 result.AppendError ("unable make a pointer type\n");
484 result.SetStatus(eReturnStatusFailed);
485 return false;
486 }
487 --pointer_count;
488 }
489
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000490 m_memory_options.m_byte_size = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000491
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000492 if (m_memory_options.m_byte_size == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000493 {
494 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
495 view_as_type_cstr);
496 result.SetStatus(eReturnStatusFailed);
497 return false;
498 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000499
500 if (!m_memory_options.m_count.OptionWasSet())
501 m_memory_options.m_count = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000502 }
503 else
504 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000505 error = m_memory_options.FinalizeSettings (exe_ctx.target, m_format_options);
506 }
507
508 // Look for invalid combinations of settings
509 if (error.Fail())
510 {
511 result.AppendErrorWithFormat("%s", error.AsCString());
512 result.SetStatus(eReturnStatusFailed);
513 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000514 }
515
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000516 size_t item_count = m_memory_options.m_count.GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000517 const size_t item_byte_size = m_memory_options.m_byte_size;
518 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000519
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000520 size_t total_byte_size = item_count * item_byte_size;
Chris Lattner24943d22010-06-08 16:52:24 +0000521 if (total_byte_size == 0)
522 total_byte_size = 32;
523
524 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
525
526 if (addr == LLDB_INVALID_ADDRESS)
527 {
528 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
529 result.SetStatus(eReturnStatusFailed);
530 return false;
531 }
532
533 if (argc == 2)
534 {
535 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
536 if (end_addr == LLDB_INVALID_ADDRESS)
537 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000538 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000539 result.SetStatus(eReturnStatusFailed);
540 return false;
541 }
542 else if (end_addr <= addr)
543 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000544 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 +0000545 result.SetStatus(eReturnStatusFailed);
546 return false;
547 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000548 else if (m_memory_options.m_count.OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000549 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000550 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 +0000551 result.SetStatus(eReturnStatusFailed);
552 return false;
553 }
554
555 total_byte_size = end_addr - addr;
556 item_count = total_byte_size / item_byte_size;
557 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000558
559 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000560 size_t bytes_read = 0;
561 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000562 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000563 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
564 bytes_read = exe_ctx.process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
565 if (bytes_read == 0)
566 {
567 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
568 result.AppendError(error.AsCString());
569 result.SetStatus(eReturnStatusFailed);
570 return false;
571 }
572
573 if (bytes_read < total_byte_size)
574 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 +0000575 }
576
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000577 StreamFile outfile_stream;
578 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000579 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
580 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000581 {
582 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000583 outfile_spec.GetPath (path, sizeof(path));
584
585 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
586 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
587 if (append)
588 open_options |= File::eOpenOptionAppend;
589
590 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000591 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000592 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000593 {
594 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
595 if (bytes_written > 0)
596 {
597 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
598 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000599 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000600 path);
601 return true;
602 }
603 else
604 {
605 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
606 result.SetStatus(eReturnStatusFailed);
607 return false;
608 }
609 }
610 else
611 {
612 // We are going to write ASCII to the file just point the
613 // output_stream to our outfile_stream...
614 output_stream = &outfile_stream;
615 }
616 }
617 else
618 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000619 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000620 result.SetStatus(eReturnStatusFailed);
621 return false;
622 }
623 }
624 else
625 {
626 output_stream = &result.GetOutputStream();
627 }
628
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000629
630 if (clang_ast_type.GetOpaqueQualType())
631 {
632 for (uint32_t i = 0; i<item_count; ++i)
633 {
634 addr_t item_addr = addr + (i * item_byte_size);
635 Address address (NULL, item_addr);
636 StreamString name_strm;
637 name_strm.Printf ("0x%llx", item_addr);
638 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
639 name_strm.GetString().c_str(),
640 address,
641 clang_ast_type));
642 if (valobj_sp)
643 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000644 if (format != eFormatDefault)
645 valobj_sp->SetFormat (format);
646
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,
Jim Ingham10de7d12011-05-04 03:43:18 +0000658 m_varobj_options.use_dynamic,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000659 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
Greg Clayton307fa072011-06-17 23:50:44 +00001066 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001067 case eFormatChar:
1068 case eFormatCString:
1069 if (value_str[0])
1070 {
1071 size_t len = strlen (value_str);
1072 // Include the NULL for C strings...
1073 if (m_options.m_format == eFormatCString)
1074 ++len;
1075 Error error;
1076 if (process->WriteMemory (addr, value_str, len, error) == len)
1077 {
1078 addr += len;
1079 }
1080 else
1081 {
1082 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1083 result.SetStatus(eReturnStatusFailed);
1084 return false;
1085 }
1086 }
1087 break;
1088
1089 case eFormatDecimal:
1090 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1091 if (!success)
1092 {
1093 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1094 result.SetStatus(eReturnStatusFailed);
1095 return false;
1096 }
1097 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1098 {
1099 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
1100 result.SetStatus(eReturnStatusFailed);
1101 return false;
1102 }
1103 buffer.PutMaxHex64 (sval64, item_byte_size);
1104 break;
1105
1106 case eFormatUnsigned:
1107 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1108 if (!success)
1109 {
1110 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1111 result.SetStatus(eReturnStatusFailed);
1112 return false;
1113 }
1114 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1115 {
1116 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1117 result.SetStatus(eReturnStatusFailed);
1118 return false;
1119 }
1120 buffer.PutMaxHex64 (uval64, item_byte_size);
1121 break;
1122
1123 case eFormatOctal:
1124 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1125 if (!success)
1126 {
1127 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1128 result.SetStatus(eReturnStatusFailed);
1129 return false;
1130 }
1131 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1132 {
1133 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1134 result.SetStatus(eReturnStatusFailed);
1135 return false;
1136 }
1137 buffer.PutMaxHex64 (uval64, item_byte_size);
1138 break;
1139 }
1140 }
1141
1142 if (!buffer.GetString().empty())
1143 {
1144 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001145 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001146 return true;
1147 else
1148 {
1149 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1150 result.SetStatus(eReturnStatusFailed);
1151 return false;
1152 }
1153 }
1154 return true;
1155 }
1156
1157protected:
1158 CommandOptions m_options;
1159};
1160
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001161#define SET1 LLDB_OPT_SET_1
1162#define SET2 LLDB_OPT_SET_2
1163
Greg Claytonb3448432011-03-24 21:19:54 +00001164OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +00001165CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
1166{
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001167{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."},
1168{ SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."},
1169{ SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1170{ SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
1171{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001172};
1173
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001174#undef SET1
1175#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +00001176
1177//-------------------------------------------------------------------------
1178// CommandObjectMemory
1179//-------------------------------------------------------------------------
1180
Greg Clayton63094e02010-06-23 01:19:29 +00001181CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001182 CommandObjectMultiword (interpreter,
1183 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001184 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001185 "memory <subcommand> [<subcommand-options>]")
1186{
Greg Clayton238c0a12010-09-18 01:14:36 +00001187 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1188 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001189}
1190
1191CommandObjectMemory::~CommandObjectMemory ()
1192{
1193}