blob: 91144e5d7b4a7231edb4309c2d6a6538c7685970 [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 Clayton56bbdaf2011-04-28 20:55:26 +0000646 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000647
648 ValueObject::DumpValueObject (*output_stream,
649 valobj_sp.get(),
650 NULL,
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000651 m_varobj_options.ptr_depth,
652 0,
653 m_varobj_options.max_depth,
654 m_varobj_options.show_types,
655 m_varobj_options.show_location,
656 m_varobj_options.use_objc,
Jim Ingham10de7d12011-05-04 03:43:18 +0000657 m_varobj_options.use_dynamic,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000658 scope_already_checked,
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000659 m_varobj_options.flat_output);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000660 }
661 else
662 {
663 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
664 view_as_type_cstr,
665 name_strm.GetString().c_str());
666 result.SetStatus(eReturnStatusFailed);
667 return false;
668 }
669 }
670 return true;
671 }
672
673 result.SetStatus(eReturnStatusSuccessFinishResult);
674 DataExtractor data (data_sp,
675 exe_ctx.target->GetArchitecture().GetByteOrder(),
676 exe_ctx.target->GetArchitecture().GetAddressByteSize());
677
678
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000679 assert (output_stream);
680 data.Dump (output_stream,
681 0,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000682 m_format_options.GetFormat(),
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000683 item_byte_size,
684 item_count,
685 num_per_line,
686 addr,
687 0,
688 0);
689 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000690 return true;
691 }
692
693protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000694// CommandOptions m_options;
695 OptionGroupOptions m_option_group;
696 OptionGroupFormat m_format_options;
697 OptionGroupReadMemory m_memory_options;
698 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000699 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000700
Chris Lattner24943d22010-06-08 16:52:24 +0000701};
702
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000703//OptionDefinition
704//CommandObjectMemoryRead::CommandOptions::g_option_table[] =
705//{
706//{ 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)."},
707//{ LLDB_OPT_SET_1, false, "size" ,'s', required_argument, NULL, 0, eArgTypeByteSize ,"The size in bytes to use when displaying with the selected format."},
708//{ LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
709//{ LLDB_OPT_SET_1|
710// LLDB_OPT_SET_2|
711// LLDB_OPT_SET_3, false, "count" ,'c', required_argument, NULL, 0, eArgTypeCount ,"The number of total items to display."},
712//{ LLDB_OPT_SET_1|
713// LLDB_OPT_SET_2|
714// LLDB_OPT_SET_3, false, "outfile" ,'o', required_argument, NULL, 0, eArgTypeFilename ,"Dump memory read results into a file."},
715//{ LLDB_OPT_SET_1|
716// LLDB_OPT_SET_2|
717// LLDB_OPT_SET_3, false, "append" ,'a', no_argument , NULL, 0, eArgTypeNone ,"Append memory read results to 'outfile'."},
718//{ 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."},
719//{ LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
720//{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
721//};
Chris Lattner24943d22010-06-08 16:52:24 +0000722
723//----------------------------------------------------------------------
724// Write memory to the inferior process
725//----------------------------------------------------------------------
726class CommandObjectMemoryWrite : public CommandObject
727{
728public:
729
730 class CommandOptions : public Options
731 {
732 public:
Greg Claytonf15996e2011-04-07 22:46:35 +0000733 CommandOptions (CommandInterpreter &interpreter) :
734 Options(interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000735 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000736 OptionParsingStarting();
Chris Lattner24943d22010-06-08 16:52:24 +0000737 }
738
739 virtual
740 ~CommandOptions ()
741 {
742 }
743
744 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000745 SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000746 {
747 Error error;
748 char short_option = (char) m_getopt_table[option_idx].val;
749 switch (short_option)
750 {
751 case 'f':
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000752 error = Args::StringToFormat (option_arg, m_format, &m_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +0000753 break;
754
755 case 's':
756 m_byte_size = Args::StringToUInt32 (option_arg, 0);
757 if (m_byte_size == 0)
758 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
759 break;
760
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000761 case 'i':
Greg Clayton537a7a82010-10-20 20:54:39 +0000762 m_infile.SetFile (option_arg, true);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000763 if (!m_infile.Exists())
764 {
765 m_infile.Clear();
766 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg);
767 }
768 break;
769
770 case 'o':
771 {
772 bool success;
773 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
774 if (!success)
775 {
776 error.SetErrorStringWithFormat("Invalid offset string '%s'\n", option_arg);
777 }
778 }
779 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000780
781 default:
782 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
783 break;
784 }
785 return error;
786 }
787
788 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000789 OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000790 {
Chris Lattner24943d22010-06-08 16:52:24 +0000791 m_format = eFormatBytes;
792 m_byte_size = 1;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000793 m_infile.Clear();
794 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000795 }
796
Greg Claytonb3448432011-03-24 21:19:54 +0000797 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000798 GetDefinitions ()
799 {
800 return g_option_table;
801 }
802
803 // Options table: Required for subclasses of Options.
804
Greg Claytonb3448432011-03-24 21:19:54 +0000805 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000806
807 // Instance variables to hold the values for command options.
808 lldb::Format m_format;
809 uint32_t m_byte_size;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000810 FileSpec m_infile;
811 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000812 };
813
Greg Clayton238c0a12010-09-18 01:14:36 +0000814 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
815 CommandObject (interpreter,
816 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000817 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000818 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
819 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000820 eFlagProcessMustBeLaunched),
821 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000822 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000823 CommandArgumentEntry arg1;
824 CommandArgumentEntry arg2;
825 CommandArgumentData addr_arg;
826 CommandArgumentData value_arg;
827
828 // Define the first (and only) variant of this arg.
829 addr_arg.arg_type = eArgTypeAddress;
830 addr_arg.arg_repetition = eArgRepeatPlain;
831
832 // There is only one variant this argument could be; put it into the argument entry.
833 arg1.push_back (addr_arg);
834
835 // Define the first (and only) variant of this arg.
836 value_arg.arg_type = eArgTypeValue;
837 value_arg.arg_repetition = eArgRepeatPlus;
838
839 // There is only one variant this argument could be; put it into the argument entry.
840 arg2.push_back (value_arg);
841
842 // Push the data for the first argument into the m_arguments vector.
843 m_arguments.push_back (arg1);
844 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000845 }
846
847 virtual
848 ~CommandObjectMemoryWrite ()
849 {
850 }
851
852 Options *
853 GetOptions ()
854 {
855 return &m_options;
856 }
857
858 bool
859 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
860 {
861 if (total_byte_size > 8)
862 return false;
863
864 if (total_byte_size == 8)
865 return true;
866
867 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
868 return uval64 <= max;
869 }
870
871 bool
872 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
873 {
874 if (total_byte_size > 8)
875 return false;
876
877 if (total_byte_size == 8)
878 return true;
879
880 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
881 const int64_t min = ~(max);
882 return min <= sval64 && sval64 <= max;
883 }
884
885 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000886 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000887 CommandReturnObject &result)
888 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000889 Process *process = m_interpreter.GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000890 if (process == NULL)
891 {
892 result.AppendError("need a process to read memory");
893 result.SetStatus(eReturnStatusFailed);
894 return false;
895 }
896
897 const size_t argc = command.GetArgumentCount();
898
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000899 if (m_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000900 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000901 if (argc < 1)
902 {
903 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
904 result.SetStatus(eReturnStatusFailed);
905 return false;
906 }
907 }
908 else if (argc < 2)
909 {
910 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 +0000911 result.SetStatus(eReturnStatusFailed);
912 return false;
913 }
914
Chris Lattner24943d22010-06-08 16:52:24 +0000915 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000916 process->GetTarget().GetArchitecture().GetAddressByteSize(),
917 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000918
Greg Clayton54e7afa2010-07-09 20:39:50 +0000919 size_t item_byte_size = m_options.m_byte_size;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000920
Chris Lattner24943d22010-06-08 16:52:24 +0000921 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
922
923 if (addr == LLDB_INVALID_ADDRESS)
924 {
925 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
926 result.SetStatus(eReturnStatusFailed);
927 return false;
928 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000929
930 if (m_options.m_infile)
931 {
932 size_t length = SIZE_MAX;
933 if (m_options.m_byte_size > 0)
934 length = m_options.m_byte_size;
935 lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length));
936 if (data_sp)
937 {
938 length = data_sp->GetByteSize();
939 if (length > 0)
940 {
941 Error error;
942 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
943
944 if (bytes_written == length)
945 {
946 // All bytes written
947 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
948 result.SetStatus(eReturnStatusSuccessFinishResult);
949 }
950 else if (bytes_written > 0)
951 {
952 // Some byte written
953 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
954 result.SetStatus(eReturnStatusSuccessFinishResult);
955 }
956 else
957 {
958 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
959 result.SetStatus(eReturnStatusFailed);
960 }
961 }
962 }
963 else
964 {
965 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
966 result.SetStatus(eReturnStatusFailed);
967 }
968 return result.Succeeded();
969 }
970 else if (m_options.m_byte_size == 0)
971 {
972 if (m_options.m_format == eFormatPointer)
973 item_byte_size = buffer.GetAddressByteSize();
974 else
975 item_byte_size = 1;
976 }
977
Chris Lattner24943d22010-06-08 16:52:24 +0000978 command.Shift(); // shift off the address argument
979 uint64_t uval64;
980 int64_t sval64;
981 bool success = false;
982 const uint32_t num_value_args = command.GetArgumentCount();
983 uint32_t i;
984 for (i=0; i<num_value_args; ++i)
985 {
986 const char *value_str = command.GetArgumentAtIndex(i);
987
988 switch (m_options.m_format)
989 {
990 case eFormatFloat: // TODO: add support for floats soon
991 case eFormatCharPrintable:
992 case eFormatBytesWithASCII:
993 case eFormatComplex:
994 case eFormatEnum:
995 case eFormatUnicode16:
996 case eFormatUnicode32:
997 case eFormatVectorOfChar:
998 case eFormatVectorOfSInt8:
999 case eFormatVectorOfUInt8:
1000 case eFormatVectorOfSInt16:
1001 case eFormatVectorOfUInt16:
1002 case eFormatVectorOfSInt32:
1003 case eFormatVectorOfUInt32:
1004 case eFormatVectorOfSInt64:
1005 case eFormatVectorOfUInt64:
1006 case eFormatVectorOfFloat32:
1007 case eFormatVectorOfFloat64:
1008 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001009 case eFormatOSType:
1010 case eFormatComplexInteger:
Chris Lattner24943d22010-06-08 16:52:24 +00001011 result.AppendError("unsupported format for writing memory");
1012 result.SetStatus(eReturnStatusFailed);
1013 return false;
1014
1015 case eFormatDefault:
1016 case eFormatBytes:
1017 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001018 case eFormatPointer:
1019
Chris Lattner24943d22010-06-08 16:52:24 +00001020 // Decode hex bytes
1021 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1022 if (!success)
1023 {
1024 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1025 result.SetStatus(eReturnStatusFailed);
1026 return false;
1027 }
1028 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1029 {
1030 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1031 result.SetStatus(eReturnStatusFailed);
1032 return false;
1033 }
1034 buffer.PutMaxHex64 (uval64, item_byte_size);
1035 break;
1036
1037 case eFormatBoolean:
1038 uval64 = Args::StringToBoolean(value_str, false, &success);
1039 if (!success)
1040 {
1041 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1042 result.SetStatus(eReturnStatusFailed);
1043 return false;
1044 }
1045 buffer.PutMaxHex64 (uval64, item_byte_size);
1046 break;
1047
1048 case eFormatBinary:
1049 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1050 if (!success)
1051 {
1052 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1053 result.SetStatus(eReturnStatusFailed);
1054 return false;
1055 }
1056 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1057 {
1058 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1059 result.SetStatus(eReturnStatusFailed);
1060 return false;
1061 }
1062 buffer.PutMaxHex64 (uval64, item_byte_size);
1063 break;
1064
1065 case eFormatChar:
1066 case eFormatCString:
1067 if (value_str[0])
1068 {
1069 size_t len = strlen (value_str);
1070 // Include the NULL for C strings...
1071 if (m_options.m_format == eFormatCString)
1072 ++len;
1073 Error error;
1074 if (process->WriteMemory (addr, value_str, len, error) == len)
1075 {
1076 addr += len;
1077 }
1078 else
1079 {
1080 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1081 result.SetStatus(eReturnStatusFailed);
1082 return false;
1083 }
1084 }
1085 break;
1086
1087 case eFormatDecimal:
1088 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1089 if (!success)
1090 {
1091 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1092 result.SetStatus(eReturnStatusFailed);
1093 return false;
1094 }
1095 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1096 {
1097 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
1098 result.SetStatus(eReturnStatusFailed);
1099 return false;
1100 }
1101 buffer.PutMaxHex64 (sval64, item_byte_size);
1102 break;
1103
1104 case eFormatUnsigned:
1105 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1106 if (!success)
1107 {
1108 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1109 result.SetStatus(eReturnStatusFailed);
1110 return false;
1111 }
1112 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1113 {
1114 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1115 result.SetStatus(eReturnStatusFailed);
1116 return false;
1117 }
1118 buffer.PutMaxHex64 (uval64, item_byte_size);
1119 break;
1120
1121 case eFormatOctal:
1122 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1123 if (!success)
1124 {
1125 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1126 result.SetStatus(eReturnStatusFailed);
1127 return false;
1128 }
1129 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1130 {
1131 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
1132 result.SetStatus(eReturnStatusFailed);
1133 return false;
1134 }
1135 buffer.PutMaxHex64 (uval64, item_byte_size);
1136 break;
1137 }
1138 }
1139
1140 if (!buffer.GetString().empty())
1141 {
1142 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001143 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001144 return true;
1145 else
1146 {
1147 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1148 result.SetStatus(eReturnStatusFailed);
1149 return false;
1150 }
1151 }
1152 return true;
1153 }
1154
1155protected:
1156 CommandOptions m_options;
1157};
1158
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001159#define SET1 LLDB_OPT_SET_1
1160#define SET2 LLDB_OPT_SET_2
1161
Greg Claytonb3448432011-03-24 21:19:54 +00001162OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +00001163CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
1164{
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001165{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."},
1166{ SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."},
1167{ SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1168{ SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
1169{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001170};
1171
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001172#undef SET1
1173#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +00001174
1175//-------------------------------------------------------------------------
1176// CommandObjectMemory
1177//-------------------------------------------------------------------------
1178
Greg Clayton63094e02010-06-23 01:19:29 +00001179CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001180 CommandObjectMultiword (interpreter,
1181 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001182 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001183 "memory <subcommand> [<subcommand-options>]")
1184{
Greg Clayton238c0a12010-09-18 01:14:36 +00001185 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1186 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001187}
1188
1189CommandObjectMemory::~CommandObjectMemory ()
1190{
1191}