blob: 71c98855e4dbeaefc7dfe3b454ae097de82e5981 [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"
Chris Lattner24943d22010-06-08 16:52:24 +000027#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000028#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000029
30using namespace lldb;
31using namespace lldb_private;
32
Greg Clayton57b3c6b2011-04-27 22:04:39 +000033OptionDefinition
34g_option_table[] =
35{
36 { LLDB_OPT_SET_1|
37 LLDB_OPT_SET_2, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize ,"The size in bytes to use when displaying with the selected format."},
38 { LLDB_OPT_SET_1|
39 LLDB_OPT_SET_3, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount ,"The number of total items to display."},
40 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
41 { 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."},
42 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
43};
44
45
46
47class OptionGroupReadMemory : public OptionGroup
48{
49public:
50
51 OptionGroupReadMemory () :
52 m_byte_size (0,0),
53 m_count (0,0),
54 m_num_per_line (0,0),
55 m_output_as_binary (false),
56 m_view_as_type()
57 {
58 }
59
60 virtual
61 ~OptionGroupReadMemory ()
62 {
63 }
64
65
66 virtual uint32_t
67 GetNumDefinitions ()
68 {
69 return sizeof (g_option_table) / sizeof (OptionDefinition);
70 }
71
72 virtual const OptionDefinition*
73 GetDefinitions ()
74 {
75 return g_option_table;
76 }
77
78 virtual Error
79 SetOptionValue (CommandInterpreter &interpreter,
80 uint32_t option_idx,
81 const char *option_arg)
82 {
83 Error error;
84 char short_option = (char) g_option_table[option_idx].short_option;
85
86 switch (short_option)
87 {
88 case 'l':
89 error = m_num_per_line.SetValueFromCString (option_arg);
90 if (m_num_per_line.GetCurrentValue() == 0)
91 error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
92 break;
93
94 case 'c':
95 error = m_count.SetValueFromCString (option_arg);
96 if (m_count.GetCurrentValue() == 0)
97 error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
98 break;
99
100 case 's':
101 error = m_byte_size.SetValueFromCString (option_arg);
102 if (m_byte_size.GetCurrentValue() == 0)
103 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
104 break;
105
106 case 'b':
107 m_output_as_binary = true;
108 break;
109
110 case 't':
111 error = m_view_as_type.SetValueFromCString (option_arg);
112 break;
113
114 default:
115 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
116 break;
117 }
118 return error;
119 }
120
121 virtual void
122 OptionParsingStarting (CommandInterpreter &interpreter)
123 {
124 m_byte_size.Clear();
125 m_count.Clear();
126 m_num_per_line.Clear();
127 m_output_as_binary = false;
128 m_view_as_type.Clear();
129 }
130
131 void
132 FinalizeSettings (lldb::Format format)
133 {
134 if (m_num_per_line.GetCurrentValue() == 0)
135 m_num_per_line.SetCurrentValue(1);
136
137 switch (format)
138 {
139 default:
140 break;
141
142 case eFormatBoolean:
143 if (m_byte_size.GetCurrentValue() == 0)
144 m_byte_size = 1;
145 break;
146
147 case eFormatCString:
148 break;
149
150 case eFormatPointer:
151 break;
152
153 case eFormatBinary:
154 case eFormatFloat:
155 case eFormatOctal:
156 case eFormatDecimal:
157 case eFormatEnum:
158 case eFormatUnicode16:
159 case eFormatUnicode32:
160 case eFormatUnsigned:
161 if (m_byte_size.GetCurrentValue() == 0)
162 m_byte_size = 4;
163 break;
164
165 case eFormatBytes:
166 case eFormatBytesWithASCII:
167 if (m_byte_size.GetCurrentValue() == 0)
168 m_byte_size = 1;
169 break;
170 case eFormatChar:
171 case eFormatCharPrintable:
172 if (m_byte_size.GetCurrentValue() == 0)
173 m_byte_size = 1;
174 break;
175 case eFormatComplex:
176 if (m_byte_size.GetCurrentValue() == 0)
177 m_byte_size = 8;
178 break;
179 case eFormatHex:
180 if (m_byte_size.GetCurrentValue() == 0)
181 m_byte_size = 4;
182 break;
183
184 case eFormatVectorOfChar:
185 case eFormatVectorOfSInt8:
186 case eFormatVectorOfUInt8:
187 case eFormatVectorOfSInt16:
188 case eFormatVectorOfUInt16:
189 case eFormatVectorOfSInt32:
190 case eFormatVectorOfUInt32:
191 case eFormatVectorOfSInt64:
192 case eFormatVectorOfUInt64:
193 case eFormatVectorOfFloat32:
194 case eFormatVectorOfFloat64:
195 case eFormatVectorOfUInt128:
196 break;
197 }
198 }
199
200 OptionValueUInt64 m_byte_size;
201 OptionValueUInt64 m_count;
202 OptionValueUInt64 m_num_per_line;
203 bool m_output_as_binary;
204 OptionValueString m_view_as_type;
205};
206
207
208
Chris Lattner24943d22010-06-08 16:52:24 +0000209//----------------------------------------------------------------------
210// Read memory from the inferior process
211//----------------------------------------------------------------------
212class CommandObjectMemoryRead : public CommandObject
213{
214public:
215
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000216// class CommandOptions : public Options
217// {
218// public:
219// CommandOptions (CommandInterpreter &interpreter) :
220// Options(interpreter)
221// {
222// OptionParsingStarting();
223// }
224//
225// virtual
226// ~CommandOptions ()
227// {
228// }
229//
230// virtual Error
231// SetOptionValue (uint32_t option_idx, const char *option_arg)
232// {
233// Error error;
234// char short_option = (char) m_getopt_table[option_idx].val;
235//
236// switch (short_option)
237// {
238// case 'f':
239// error = Args::StringToFormat (option_arg, m_format);
240//
241// switch (m_format)
242// {
243// default:
244// break;
245//
246// case eFormatBoolean:
247// if (m_byte_size == 0)
248// m_byte_size = 1;
249// if (m_num_per_line == 0)
250// m_num_per_line = 1;
251// break;
252//
253// case eFormatCString:
254// if (m_num_per_line == 0)
255// m_num_per_line = 1;
256// break;
257//
258// case eFormatPointer:
259// break;
260//
261// case eFormatBinary:
262// case eFormatFloat:
263// case eFormatOctal:
264// case eFormatDecimal:
265// case eFormatEnum:
266// case eFormatUnicode16:
267// case eFormatUnicode32:
268// case eFormatUnsigned:
269// if (m_byte_size == 0)
270// m_byte_size = 4;
271// if (m_num_per_line == 0)
272// m_num_per_line = 1;
273// break;
274//
275// case eFormatBytes:
276// case eFormatBytesWithASCII:
277// case eFormatChar:
278// case eFormatCharPrintable:
279// if (m_byte_size == 0)
280// m_byte_size = 1;
281// break;
282// case eFormatComplex:
283// if (m_byte_size == 0)
284// m_byte_size = 8;
285// break;
286// case eFormatHex:
287// if (m_byte_size == 0)
288// m_byte_size = 4;
289// break;
290//
291// case eFormatVectorOfChar:
292// case eFormatVectorOfSInt8:
293// case eFormatVectorOfUInt8:
294// case eFormatVectorOfSInt16:
295// case eFormatVectorOfUInt16:
296// case eFormatVectorOfSInt32:
297// case eFormatVectorOfUInt32:
298// case eFormatVectorOfSInt64:
299// case eFormatVectorOfUInt64:
300// case eFormatVectorOfFloat32:
301// case eFormatVectorOfFloat64:
302// case eFormatVectorOfUInt128:
303// break;
304// }
305// break;
306//
307// case 'l':
308// m_num_per_line = Args::StringToUInt32 (option_arg, 0);
309// if (m_num_per_line == 0)
310// error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
311// break;
312//
313// case 'c':
314// m_count = Args::StringToUInt32 (option_arg, 0);
315// if (m_count == 0)
316// error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
317// break;
318//
319// case 's':
320// m_byte_size = Args::StringToUInt32 (option_arg, 0);
321// if (m_byte_size == 0)
322// error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
323// break;
324//
325// case 'o':
326// m_outfile_filespec.SetFile (option_arg, true);
327// break;
328//
329// case 'b':
330// m_output_as_binary = true;
331// break;
332//
333// case 'a':
334// m_append_to_outfile = true;
335// break;
336//
337// case 't':
338// m_view_as_type.assign (option_arg);
339// break;
340//
341// default:
342// error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
343// break;
344// }
345// return error;
346// }
347//
348// void
349// OptionParsingStarting ()
350// {
351// m_format = eFormatBytesWithASCII;
352// m_byte_size = 0;
353// m_count = 0;
354// m_num_per_line = 0;
355// m_outfile_filespec.Clear();
356// m_view_as_type.clear();
357// m_append_to_outfile = false;
358// m_output_as_binary = false;
359// }
360//
361// const OptionDefinition*
362// GetDefinitions ()
363// {
364// return g_option_table;
365// }
366//
367// // Options table: Required for subclasses of Options.
368//
369// static OptionDefinition g_option_table[];
370//
371// // Instance variables to hold the values for command options.
372// lldb::Format m_format;
373// uint32_t m_byte_size;
374// uint32_t m_count;
375// uint32_t m_num_per_line;
376// FileSpec m_outfile_filespec;
377// std::string m_view_as_type;
378// bool m_append_to_outfile;
379// bool m_output_as_binary;
380// };
Chris Lattner24943d22010-06-08 16:52:24 +0000381
Greg Clayton238c0a12010-09-18 01:14:36 +0000382 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
383 CommandObject (interpreter,
384 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000385 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000386 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000387 eFlagProcessMustBeLaunched),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000388 m_option_group (interpreter),
389 m_format_options (eFormatBytesWithASCII),
390 m_memory_options (),
391 m_outfile_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000392 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000393 CommandArgumentEntry arg1;
394 CommandArgumentEntry arg2;
395 CommandArgumentData start_addr_arg;
396 CommandArgumentData end_addr_arg;
397
398 // Define the first (and only) variant of this arg.
399 start_addr_arg.arg_type = eArgTypeStartAddress;
400 start_addr_arg.arg_repetition = eArgRepeatPlain;
401
402 // There is only one variant this argument could be; put it into the argument entry.
403 arg1.push_back (start_addr_arg);
404
405 // Define the first (and only) variant of this arg.
406 end_addr_arg.arg_type = eArgTypeEndAddress;
407 end_addr_arg.arg_repetition = eArgRepeatOptional;
408
409 // There is only one variant this argument could be; put it into the argument entry.
410 arg2.push_back (end_addr_arg);
411
412 // Push the data for the first argument into the m_arguments vector.
413 m_arguments.push_back (arg1);
414 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000415
416 m_option_group.Append (&m_format_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
417 m_option_group.Append (&m_memory_options);
418 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
419 m_option_group.Finalize();
420
Chris Lattner24943d22010-06-08 16:52:24 +0000421 }
422
423 virtual
424 ~CommandObjectMemoryRead ()
425 {
426 }
427
428 Options *
429 GetOptions ()
430 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000431 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000432 }
433
434 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000435 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000436 CommandReturnObject &result)
437 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000438 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
439 if (exe_ctx.process == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000440 {
441 result.AppendError("need a process to read memory");
442 result.SetStatus(eReturnStatusFailed);
443 return false;
444 }
445 const size_t argc = command.GetArgumentCount();
446
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000447
Chris Lattner24943d22010-06-08 16:52:24 +0000448 if (argc == 0 || argc > 2)
449 {
450 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
451 result.SetStatus(eReturnStatusFailed);
452 return false;
453 }
454
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000455 size_t item_byte_size = m_memory_options.m_byte_size.GetCurrentValue();
456 ClangASTType clang_ast_type;
457
458 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
459 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000460 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000461 // We are viewing memory as a type
462 SymbolContext sc;
463 const bool append = true;
464 TypeList type_list;
465 uint32_t reference_count = 0;
466 uint32_t pointer_count = 0;
467 size_t idx;
468 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
469 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
470 std::string type_str(view_as_type_cstr);
471
472 // Remove all instances of g_keywords that are followed by spaces
473 for (size_t i = 0; i < g_num_keywords; ++i)
474 {
475 const char *keyword = g_keywords[i];
476 int keyword_len = ::strlen (keyword);
477 while ((idx = type_str.find (keyword)) != std::string::npos)
478 {
479 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
480 type_str.erase(idx, keyword_len+1);
481 }
482 }
483 bool done = type_str.empty();
484 //
485 idx = type_str.find_first_not_of (" \t");
486 if (idx > 0 && idx != std::string::npos)
487 type_str.erase (0, idx);
488 while (!done)
489 {
490 // Strip trailing spaces
491 if (type_str.empty())
492 done = true;
493 else
494 {
495 switch (type_str[type_str.size()-1])
496 {
497 case '*':
498 ++pointer_count;
499 // fall through...
500 case ' ':
501 case '\t':
502 type_str.erase(type_str.size()-1);
503 break;
504
505 case '&':
506 if (reference_count == 0)
507 {
508 reference_count = 1;
509 type_str.erase(type_str.size()-1);
510 }
511 else
512 {
513 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
514 result.SetStatus(eReturnStatusFailed);
515 return false;
516 }
517 break;
518
519 default:
520 done = true;
521 break;
522 }
523 }
524 }
525
526 ConstString lookup_type_name(type_str.c_str());
527 if (exe_ctx.frame)
528 {
529 sc = exe_ctx.frame->GetSymbolContext (eSymbolContextModule);
530 if (sc.module_sp)
531 {
532 sc.module_sp->FindTypes (sc,
533 lookup_type_name,
534 append,
535 1,
536 type_list);
537 }
538 }
539 if (type_list.GetSize() == 0)
540 {
541 exe_ctx.target->GetImages().FindTypes (sc,
542 lookup_type_name,
543 append,
544 1,
545 type_list);
546 }
547
548 if (type_list.GetSize() == 0)
549 {
550 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
551 lookup_type_name.GetCString(),
552 view_as_type_cstr);
553 result.SetStatus(eReturnStatusFailed);
554 return false;
555 }
556
557 TypeSP type_sp (type_list.GetTypeAtIndex(0));
558 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
559
560 while (pointer_count > 0)
561 {
562 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
563 if (pointer_type)
564 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
565 else
566 {
567 result.AppendError ("unable make a pointer type\n");
568 result.SetStatus(eReturnStatusFailed);
569 return false;
570 }
571 --pointer_count;
572 }
573
574 item_byte_size = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
575
576 if (item_byte_size == 0)
577 {
578 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
579 view_as_type_cstr);
580 result.SetStatus(eReturnStatusFailed);
581 return false;
582 }
583 }
584 else
585 {
586 if (item_byte_size == 0)
587 {
588 if (m_format_options.GetFormat() == eFormatPointer)
589 item_byte_size = exe_ctx.target->GetArchitecture().GetAddressByteSize();
590 else
591 item_byte_size = 1;
592 }
Chris Lattner24943d22010-06-08 16:52:24 +0000593 }
594
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000595 size_t item_count = m_memory_options.m_count.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000596
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000597 size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000598 if (num_per_line == 0)
599 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000600 if (clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000601 num_per_line = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000602 else
603 {
604 num_per_line = (16/item_byte_size);
605 if (num_per_line == 0)
606 num_per_line = 1;
607 }
Chris Lattner24943d22010-06-08 16:52:24 +0000608 }
609
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000610 size_t total_byte_size = item_count * item_byte_size;
Chris Lattner24943d22010-06-08 16:52:24 +0000611 if (total_byte_size == 0)
612 total_byte_size = 32;
613
614 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
615
616 if (addr == LLDB_INVALID_ADDRESS)
617 {
618 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
619 result.SetStatus(eReturnStatusFailed);
620 return false;
621 }
622
623 if (argc == 2)
624 {
625 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
626 if (end_addr == LLDB_INVALID_ADDRESS)
627 {
628 result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
629 result.SetStatus(eReturnStatusFailed);
630 return false;
631 }
632 else if (end_addr <= addr)
633 {
634 result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
635 result.SetStatus(eReturnStatusFailed);
636 return false;
637 }
638 else if (item_count != 0)
639 {
640 result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
641 result.SetStatus(eReturnStatusFailed);
642 return false;
643 }
644
645 total_byte_size = end_addr - addr;
646 item_count = total_byte_size / item_byte_size;
647 }
648 else
649 {
650 if (item_count == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000651 {
652 if (clang_ast_type.GetOpaqueQualType())
653 item_count = 1;
654 else
655 item_count = 32;
656 }
Chris Lattner24943d22010-06-08 16:52:24 +0000657 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000658
659 DataBufferSP data_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000660 Error error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000661 size_t bytes_read = 0;
662 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000663 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000664 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
665 bytes_read = exe_ctx.process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
666 if (bytes_read == 0)
667 {
668 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
669 result.AppendError(error.AsCString());
670 result.SetStatus(eReturnStatusFailed);
671 return false;
672 }
673
674 if (bytes_read < total_byte_size)
675 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 +0000676 }
677
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000678 StreamFile outfile_stream;
679 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000680 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
681 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000682 {
683 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000684 outfile_spec.GetPath (path, sizeof(path));
685
686 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
687 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
688 if (append)
689 open_options |= File::eOpenOptionAppend;
690
691 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000692 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000693 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000694 {
695 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
696 if (bytes_written > 0)
697 {
698 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
699 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000700 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000701 path);
702 return true;
703 }
704 else
705 {
706 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
707 result.SetStatus(eReturnStatusFailed);
708 return false;
709 }
710 }
711 else
712 {
713 // We are going to write ASCII to the file just point the
714 // output_stream to our outfile_stream...
715 output_stream = &outfile_stream;
716 }
717 }
718 else
719 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000720 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000721 result.SetStatus(eReturnStatusFailed);
722 return false;
723 }
724 }
725 else
726 {
727 output_stream = &result.GetOutputStream();
728 }
729
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000730
731 if (clang_ast_type.GetOpaqueQualType())
732 {
733 for (uint32_t i = 0; i<item_count; ++i)
734 {
735 addr_t item_addr = addr + (i * item_byte_size);
736 Address address (NULL, item_addr);
737 StreamString name_strm;
738 name_strm.Printf ("0x%llx", item_addr);
739 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
740 name_strm.GetString().c_str(),
741 address,
742 clang_ast_type));
743 if (valobj_sp)
744 {
745 uint32_t ptr_depth = 0;
746 uint32_t curr_depth = 0;
747 uint32_t max_depth = UINT32_MAX;
748 bool show_types = false;
749 bool show_location = false;
750 bool use_objc = false;
751 bool use_dynamic = false;
752 bool scope_already_checked = false;
753 bool flat_output = false;
754
755 ValueObject::DumpValueObject (*output_stream,
756 valobj_sp.get(),
757 NULL,
758 ptr_depth,
759 curr_depth,
760 max_depth,
761 show_types,
762 show_location,
763 use_objc,
764 use_dynamic,
765 scope_already_checked,
766 flat_output);
767 }
768 else
769 {
770 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
771 view_as_type_cstr,
772 name_strm.GetString().c_str());
773 result.SetStatus(eReturnStatusFailed);
774 return false;
775 }
776 }
777 return true;
778 }
779
780 result.SetStatus(eReturnStatusSuccessFinishResult);
781 DataExtractor data (data_sp,
782 exe_ctx.target->GetArchitecture().GetByteOrder(),
783 exe_ctx.target->GetArchitecture().GetAddressByteSize());
784
785
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000786 assert (output_stream);
787 data.Dump (output_stream,
788 0,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000789 m_format_options.GetFormat(),
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000790 item_byte_size,
791 item_count,
792 num_per_line,
793 addr,
794 0,
795 0);
796 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000797 return true;
798 }
799
800protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000801// CommandOptions m_options;
802 OptionGroupOptions m_option_group;
803 OptionGroupFormat m_format_options;
804 OptionGroupReadMemory m_memory_options;
805 OptionGroupOutputFile m_outfile_options;
806
Chris Lattner24943d22010-06-08 16:52:24 +0000807};
808
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000809//OptionDefinition
810//CommandObjectMemoryRead::CommandOptions::g_option_table[] =
811//{
812//{ 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)."},
813//{ LLDB_OPT_SET_1, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize ,"The size in bytes to use when displaying with the selected format."},
814//{ LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
815//{ LLDB_OPT_SET_1|
816// LLDB_OPT_SET_2|
817// LLDB_OPT_SET_3, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount ,"The number of total items to display."},
818//{ LLDB_OPT_SET_1|
819// LLDB_OPT_SET_2|
820// LLDB_OPT_SET_3, false, "outfile" ,'o', required_argument, NULL, 0, eArgTypeFilename ,"Dump memory read results into a file."},
821//{ LLDB_OPT_SET_1|
822// LLDB_OPT_SET_2|
823// LLDB_OPT_SET_3, false, "append" ,'a', no_argument , NULL, 0, eArgTypeNone ,"Append memory read results to 'outfile'."},
824//{ 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."},
825//{ LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
826//{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
827//};
Chris Lattner24943d22010-06-08 16:52:24 +0000828
829//----------------------------------------------------------------------
830// Write memory to the inferior process
831//----------------------------------------------------------------------
832class CommandObjectMemoryWrite : public CommandObject
833{
834public:
835
836 class CommandOptions : public Options
837 {
838 public:
Greg Claytonf15996e2011-04-07 22:46:35 +0000839 CommandOptions (CommandInterpreter &interpreter) :
840 Options(interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000841 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000842 OptionParsingStarting();
Chris Lattner24943d22010-06-08 16:52:24 +0000843 }
844
845 virtual
846 ~CommandOptions ()
847 {
848 }
849
850 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000851 SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000852 {
853 Error error;
854 char short_option = (char) m_getopt_table[option_idx].val;
855 switch (short_option)
856 {
857 case 'f':
858 error = Args::StringToFormat (option_arg, m_format);
859 break;
860
861 case 's':
862 m_byte_size = Args::StringToUInt32 (option_arg, 0);
863 if (m_byte_size == 0)
864 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
865 break;
866
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000867 case 'i':
Greg Clayton537a7a82010-10-20 20:54:39 +0000868 m_infile.SetFile (option_arg, true);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000869 if (!m_infile.Exists())
870 {
871 m_infile.Clear();
872 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg);
873 }
874 break;
875
876 case 'o':
877 {
878 bool success;
879 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
880 if (!success)
881 {
882 error.SetErrorStringWithFormat("Invalid offset string '%s'\n", option_arg);
883 }
884 }
885 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000886
887 default:
888 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
889 break;
890 }
891 return error;
892 }
893
894 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000895 OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000896 {
Chris Lattner24943d22010-06-08 16:52:24 +0000897 m_format = eFormatBytes;
898 m_byte_size = 1;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000899 m_infile.Clear();
900 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000901 }
902
Greg Claytonb3448432011-03-24 21:19:54 +0000903 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000904 GetDefinitions ()
905 {
906 return g_option_table;
907 }
908
909 // Options table: Required for subclasses of Options.
910
Greg Claytonb3448432011-03-24 21:19:54 +0000911 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000912
913 // Instance variables to hold the values for command options.
914 lldb::Format m_format;
915 uint32_t m_byte_size;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000916 FileSpec m_infile;
917 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000918 };
919
Greg Clayton238c0a12010-09-18 01:14:36 +0000920 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
921 CommandObject (interpreter,
922 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000923 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000924 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
925 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000926 eFlagProcessMustBeLaunched),
927 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000928 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000929 CommandArgumentEntry arg1;
930 CommandArgumentEntry arg2;
931 CommandArgumentData addr_arg;
932 CommandArgumentData value_arg;
933
934 // Define the first (and only) variant of this arg.
935 addr_arg.arg_type = eArgTypeAddress;
936 addr_arg.arg_repetition = eArgRepeatPlain;
937
938 // There is only one variant this argument could be; put it into the argument entry.
939 arg1.push_back (addr_arg);
940
941 // Define the first (and only) variant of this arg.
942 value_arg.arg_type = eArgTypeValue;
943 value_arg.arg_repetition = eArgRepeatPlus;
944
945 // There is only one variant this argument could be; put it into the argument entry.
946 arg2.push_back (value_arg);
947
948 // Push the data for the first argument into the m_arguments vector.
949 m_arguments.push_back (arg1);
950 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000951 }
952
953 virtual
954 ~CommandObjectMemoryWrite ()
955 {
956 }
957
958 Options *
959 GetOptions ()
960 {
961 return &m_options;
962 }
963
964 bool
965 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
966 {
967 if (total_byte_size > 8)
968 return false;
969
970 if (total_byte_size == 8)
971 return true;
972
973 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
974 return uval64 <= max;
975 }
976
977 bool
978 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
979 {
980 if (total_byte_size > 8)
981 return false;
982
983 if (total_byte_size == 8)
984 return true;
985
986 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
987 const int64_t min = ~(max);
988 return min <= sval64 && sval64 <= max;
989 }
990
991 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000992 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000993 CommandReturnObject &result)
994 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000995 Process *process = m_interpreter.GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000996 if (process == NULL)
997 {
998 result.AppendError("need a process to read memory");
999 result.SetStatus(eReturnStatusFailed);
1000 return false;
1001 }
1002
1003 const size_t argc = command.GetArgumentCount();
1004
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001005 if (m_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +00001006 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001007 if (argc < 1)
1008 {
1009 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1010 result.SetStatus(eReturnStatusFailed);
1011 return false;
1012 }
1013 }
1014 else if (argc < 2)
1015 {
1016 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 +00001017 result.SetStatus(eReturnStatusFailed);
1018 return false;
1019 }
1020
Chris Lattner24943d22010-06-08 16:52:24 +00001021 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +00001022 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1023 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +00001024
Greg Clayton54e7afa2010-07-09 20:39:50 +00001025 size_t item_byte_size = m_options.m_byte_size;
Greg Clayton54e7afa2010-07-09 20:39:50 +00001026
Chris Lattner24943d22010-06-08 16:52:24 +00001027 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
1028
1029 if (addr == LLDB_INVALID_ADDRESS)
1030 {
1031 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
1032 result.SetStatus(eReturnStatusFailed);
1033 return false;
1034 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001035
1036 if (m_options.m_infile)
1037 {
1038 size_t length = SIZE_MAX;
1039 if (m_options.m_byte_size > 0)
1040 length = m_options.m_byte_size;
1041 lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length));
1042 if (data_sp)
1043 {
1044 length = data_sp->GetByteSize();
1045 if (length > 0)
1046 {
1047 Error error;
1048 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1049
1050 if (bytes_written == length)
1051 {
1052 // All bytes written
1053 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
1054 result.SetStatus(eReturnStatusSuccessFinishResult);
1055 }
1056 else if (bytes_written > 0)
1057 {
1058 // Some byte written
1059 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
1060 result.SetStatus(eReturnStatusSuccessFinishResult);
1061 }
1062 else
1063 {
1064 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1065 result.SetStatus(eReturnStatusFailed);
1066 }
1067 }
1068 }
1069 else
1070 {
1071 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1072 result.SetStatus(eReturnStatusFailed);
1073 }
1074 return result.Succeeded();
1075 }
1076 else if (m_options.m_byte_size == 0)
1077 {
1078 if (m_options.m_format == eFormatPointer)
1079 item_byte_size = buffer.GetAddressByteSize();
1080 else
1081 item_byte_size = 1;
1082 }
1083
Chris Lattner24943d22010-06-08 16:52:24 +00001084 command.Shift(); // shift off the address argument
1085 uint64_t uval64;
1086 int64_t sval64;
1087 bool success = false;
1088 const uint32_t num_value_args = command.GetArgumentCount();
1089 uint32_t i;
1090 for (i=0; i<num_value_args; ++i)
1091 {
1092 const char *value_str = command.GetArgumentAtIndex(i);
1093
1094 switch (m_options.m_format)
1095 {
1096 case eFormatFloat: // TODO: add support for floats soon
1097 case eFormatCharPrintable:
1098 case eFormatBytesWithASCII:
1099 case eFormatComplex:
1100 case eFormatEnum:
1101 case eFormatUnicode16:
1102 case eFormatUnicode32:
1103 case eFormatVectorOfChar:
1104 case eFormatVectorOfSInt8:
1105 case eFormatVectorOfUInt8:
1106 case eFormatVectorOfSInt16:
1107 case eFormatVectorOfUInt16:
1108 case eFormatVectorOfSInt32:
1109 case eFormatVectorOfUInt32:
1110 case eFormatVectorOfSInt64:
1111 case eFormatVectorOfUInt64:
1112 case eFormatVectorOfFloat32:
1113 case eFormatVectorOfFloat64:
1114 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001115 case eFormatOSType:
1116 case eFormatComplexInteger:
Chris Lattner24943d22010-06-08 16:52:24 +00001117 result.AppendError("unsupported format for writing memory");
1118 result.SetStatus(eReturnStatusFailed);
1119 return false;
1120
1121 case eFormatDefault:
1122 case eFormatBytes:
1123 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001124 case eFormatPointer:
1125
Chris Lattner24943d22010-06-08 16:52:24 +00001126 // Decode hex bytes
1127 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1128 if (!success)
1129 {
1130 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1131 result.SetStatus(eReturnStatusFailed);
1132 return false;
1133 }
1134 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1135 {
1136 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1137 result.SetStatus(eReturnStatusFailed);
1138 return false;
1139 }
1140 buffer.PutMaxHex64 (uval64, item_byte_size);
1141 break;
1142
1143 case eFormatBoolean:
1144 uval64 = Args::StringToBoolean(value_str, false, &success);
1145 if (!success)
1146 {
1147 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1148 result.SetStatus(eReturnStatusFailed);
1149 return false;
1150 }
1151 buffer.PutMaxHex64 (uval64, item_byte_size);
1152 break;
1153
1154 case eFormatBinary:
1155 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1156 if (!success)
1157 {
1158 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1159 result.SetStatus(eReturnStatusFailed);
1160 return false;
1161 }
1162 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1163 {
1164 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1165 result.SetStatus(eReturnStatusFailed);
1166 return false;
1167 }
1168 buffer.PutMaxHex64 (uval64, item_byte_size);
1169 break;
1170
1171 case eFormatChar:
1172 case eFormatCString:
1173 if (value_str[0])
1174 {
1175 size_t len = strlen (value_str);
1176 // Include the NULL for C strings...
1177 if (m_options.m_format == eFormatCString)
1178 ++len;
1179 Error error;
1180 if (process->WriteMemory (addr, value_str, len, error) == len)
1181 {
1182 addr += len;
1183 }
1184 else
1185 {
1186 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1187 result.SetStatus(eReturnStatusFailed);
1188 return false;
1189 }
1190 }
1191 break;
1192
1193 case eFormatDecimal:
1194 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1195 if (!success)
1196 {
1197 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1198 result.SetStatus(eReturnStatusFailed);
1199 return false;
1200 }
1201 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1202 {
1203 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
1204 result.SetStatus(eReturnStatusFailed);
1205 return false;
1206 }
1207 buffer.PutMaxHex64 (sval64, item_byte_size);
1208 break;
1209
1210 case eFormatUnsigned:
1211 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1212 if (!success)
1213 {
1214 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1215 result.SetStatus(eReturnStatusFailed);
1216 return false;
1217 }
1218 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1219 {
1220 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1221 result.SetStatus(eReturnStatusFailed);
1222 return false;
1223 }
1224 buffer.PutMaxHex64 (uval64, item_byte_size);
1225 break;
1226
1227 case eFormatOctal:
1228 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1229 if (!success)
1230 {
1231 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1232 result.SetStatus(eReturnStatusFailed);
1233 return false;
1234 }
1235 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1236 {
1237 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1238 result.SetStatus(eReturnStatusFailed);
1239 return false;
1240 }
1241 buffer.PutMaxHex64 (uval64, item_byte_size);
1242 break;
1243 }
1244 }
1245
1246 if (!buffer.GetString().empty())
1247 {
1248 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001249 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001250 return true;
1251 else
1252 {
1253 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1254 result.SetStatus(eReturnStatusFailed);
1255 return false;
1256 }
1257 }
1258 return true;
1259 }
1260
1261protected:
1262 CommandOptions m_options;
1263};
1264
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001265#define SET1 LLDB_OPT_SET_1
1266#define SET2 LLDB_OPT_SET_2
1267
Greg Claytonb3448432011-03-24 21:19:54 +00001268OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +00001269CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
1270{
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001271{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."},
1272{ SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."},
1273{ SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1274{ SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
1275{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001276};
1277
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001278#undef SET1
1279#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +00001280
1281//-------------------------------------------------------------------------
1282// CommandObjectMemory
1283//-------------------------------------------------------------------------
1284
Greg Clayton63094e02010-06-23 01:19:29 +00001285CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001286 CommandObjectMultiword (interpreter,
1287 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001288 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001289 "memory <subcommand> [<subcommand-options>]")
1290{
Greg Clayton238c0a12010-09-18 01:14:36 +00001291 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1292 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001293}
1294
1295CommandObjectMemory::~CommandObjectMemory ()
1296{
1297}