blob: 9629c8410b6c04df8f1ad833c2b74a2fbccafa86 [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,
Jim Ingham8cc3f692011-07-09 00:55:34 +0000301 eFlagProcessMustBePaused),
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());
Greg Clayton567e7f32011-09-22 04:58:26 +0000354 Target *target = exe_ctx.GetTargetPtr();
355 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000356 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000357 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000358 result.SetStatus(eReturnStatusFailed);
359 return false;
360 }
361 const size_t argc = command.GetArgumentCount();
362
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000363
Chris Lattner24943d22010-06-08 16:52:24 +0000364 if (argc == 0 || argc > 2)
365 {
366 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
367 result.SetStatus(eReturnStatusFailed);
368 return false;
369 }
370
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000371 ClangASTType clang_ast_type;
372 Error error;
373
374 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000375 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
376 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000377 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000378 // We are viewing memory as a type
379 SymbolContext sc;
380 const bool append = true;
381 TypeList type_list;
382 uint32_t reference_count = 0;
383 uint32_t pointer_count = 0;
384 size_t idx;
385 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
386 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
387 std::string type_str(view_as_type_cstr);
388
389 // Remove all instances of g_keywords that are followed by spaces
390 for (size_t i = 0; i < g_num_keywords; ++i)
391 {
392 const char *keyword = g_keywords[i];
393 int keyword_len = ::strlen (keyword);
394 while ((idx = type_str.find (keyword)) != std::string::npos)
395 {
396 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
397 type_str.erase(idx, keyword_len+1);
398 }
399 }
400 bool done = type_str.empty();
401 //
402 idx = type_str.find_first_not_of (" \t");
403 if (idx > 0 && idx != std::string::npos)
404 type_str.erase (0, idx);
405 while (!done)
406 {
407 // Strip trailing spaces
408 if (type_str.empty())
409 done = true;
410 else
411 {
412 switch (type_str[type_str.size()-1])
413 {
414 case '*':
415 ++pointer_count;
416 // fall through...
417 case ' ':
418 case '\t':
419 type_str.erase(type_str.size()-1);
420 break;
421
422 case '&':
423 if (reference_count == 0)
424 {
425 reference_count = 1;
426 type_str.erase(type_str.size()-1);
427 }
428 else
429 {
430 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
431 result.SetStatus(eReturnStatusFailed);
432 return false;
433 }
434 break;
435
436 default:
437 done = true;
438 break;
439 }
440 }
441 }
442
443 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000444 StackFrame *frame = exe_ctx.GetFramePtr();
445 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000446 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000447 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000448 if (sc.module_sp)
449 {
450 sc.module_sp->FindTypes (sc,
451 lookup_type_name,
452 append,
453 1,
454 type_list);
455 }
456 }
457 if (type_list.GetSize() == 0)
458 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000459 target->GetImages().FindTypes (sc,
460 lookup_type_name,
461 append,
462 1,
463 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000464 }
465
466 if (type_list.GetSize() == 0)
467 {
468 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
469 lookup_type_name.GetCString(),
470 view_as_type_cstr);
471 result.SetStatus(eReturnStatusFailed);
472 return false;
473 }
474
475 TypeSP type_sp (type_list.GetTypeAtIndex(0));
476 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
477
478 while (pointer_count > 0)
479 {
480 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
481 if (pointer_type)
482 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
483 else
484 {
485 result.AppendError ("unable make a pointer type\n");
486 result.SetStatus(eReturnStatusFailed);
487 return false;
488 }
489 --pointer_count;
490 }
491
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000492 m_memory_options.m_byte_size = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000493
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000494 if (m_memory_options.m_byte_size == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000495 {
496 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
497 view_as_type_cstr);
498 result.SetStatus(eReturnStatusFailed);
499 return false;
500 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000501
502 if (!m_memory_options.m_count.OptionWasSet())
503 m_memory_options.m_count = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000504 }
505 else
506 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000507 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000508 }
509
510 // Look for invalid combinations of settings
511 if (error.Fail())
512 {
513 result.AppendErrorWithFormat("%s", error.AsCString());
514 result.SetStatus(eReturnStatusFailed);
515 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000516 }
517
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000518 size_t item_count = m_memory_options.m_count.GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000519 const size_t item_byte_size = m_memory_options.m_byte_size;
520 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000521
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000522 size_t total_byte_size = item_count * item_byte_size;
Chris Lattner24943d22010-06-08 16:52:24 +0000523 if (total_byte_size == 0)
524 total_byte_size = 32;
525
526 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
527
528 if (addr == LLDB_INVALID_ADDRESS)
529 {
530 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
531 result.SetStatus(eReturnStatusFailed);
532 return false;
533 }
534
535 if (argc == 2)
536 {
537 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
538 if (end_addr == LLDB_INVALID_ADDRESS)
539 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000540 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000541 result.SetStatus(eReturnStatusFailed);
542 return false;
543 }
544 else if (end_addr <= addr)
545 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000546 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 +0000547 result.SetStatus(eReturnStatusFailed);
548 return false;
549 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000550 else if (m_memory_options.m_count.OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000551 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000552 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner24943d22010-06-08 16:52:24 +0000553 result.SetStatus(eReturnStatusFailed);
554 return false;
555 }
556
557 total_byte_size = end_addr - addr;
558 item_count = total_byte_size / item_byte_size;
559 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000560
561 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000562 size_t bytes_read = 0;
563 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000564 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000565 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Jim Ingham8cc3f692011-07-09 00:55:34 +0000566 Address address(NULL, addr);
Greg Clayton567e7f32011-09-22 04:58:26 +0000567 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000568 if (bytes_read == 0)
569 {
570 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
571 result.AppendError(error.AsCString());
572 result.SetStatus(eReturnStatusFailed);
573 return false;
574 }
575
576 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000577 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
Chris Lattner24943d22010-06-08 16:52:24 +0000578 }
579
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000580 StreamFile outfile_stream;
581 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000582 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
583 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000584 {
585 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000586 outfile_spec.GetPath (path, sizeof(path));
587
588 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
589 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
590 if (append)
591 open_options |= File::eOpenOptionAppend;
592
593 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000594 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000595 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000596 {
597 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
598 if (bytes_written > 0)
599 {
600 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
601 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000602 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000603 path);
604 return true;
605 }
606 else
607 {
608 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
609 result.SetStatus(eReturnStatusFailed);
610 return false;
611 }
612 }
613 else
614 {
615 // We are going to write ASCII to the file just point the
616 // output_stream to our outfile_stream...
617 output_stream = &outfile_stream;
618 }
619 }
620 else
621 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000622 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000623 result.SetStatus(eReturnStatusFailed);
624 return false;
625 }
626 }
627 else
628 {
629 output_stream = &result.GetOutputStream();
630 }
631
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000632
633 if (clang_ast_type.GetOpaqueQualType())
634 {
635 for (uint32_t i = 0; i<item_count; ++i)
636 {
637 addr_t item_addr = addr + (i * item_byte_size);
638 Address address (NULL, item_addr);
639 StreamString name_strm;
640 name_strm.Printf ("0x%llx", item_addr);
641 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
642 name_strm.GetString().c_str(),
643 address,
644 clang_ast_type));
645 if (valobj_sp)
646 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000647 if (format != eFormatDefault)
648 valobj_sp->SetFormat (format);
649
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000650 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000651
652 ValueObject::DumpValueObject (*output_stream,
653 valobj_sp.get(),
654 NULL,
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000655 m_varobj_options.ptr_depth,
656 0,
657 m_varobj_options.max_depth,
658 m_varobj_options.show_types,
659 m_varobj_options.show_location,
660 m_varobj_options.use_objc,
Jim Ingham10de7d12011-05-04 03:43:18 +0000661 m_varobj_options.use_dynamic,
Enrico Granata840eb262011-08-09 23:50:01 +0000662 m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000663 scope_already_checked,
Enrico Granata7f163b32011-07-16 01:22:04 +0000664 m_varobj_options.flat_output,
Enrico Granata018921d2011-08-12 02:00:06 +0000665 m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth,
666 m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000667 }
668 else
669 {
670 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
671 view_as_type_cstr,
672 name_strm.GetString().c_str());
673 result.SetStatus(eReturnStatusFailed);
674 return false;
675 }
676 }
677 return true;
678 }
679
680 result.SetStatus(eReturnStatusSuccessFinishResult);
681 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000682 target->GetArchitecture().GetByteOrder(),
683 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000684
685
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000686 assert (output_stream);
687 data.Dump (output_stream,
688 0,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000689 m_format_options.GetFormat(),
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000690 item_byte_size,
691 item_count,
692 num_per_line,
693 addr,
694 0,
695 0);
696 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000697 return true;
698 }
699
700protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000701 OptionGroupOptions m_option_group;
702 OptionGroupFormat m_format_options;
703 OptionGroupReadMemory m_memory_options;
704 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000705 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000706
Chris Lattner24943d22010-06-08 16:52:24 +0000707};
708
Chris Lattner24943d22010-06-08 16:52:24 +0000709//----------------------------------------------------------------------
710// Write memory to the inferior process
711//----------------------------------------------------------------------
712class CommandObjectMemoryWrite : public CommandObject
713{
714public:
715
716 class CommandOptions : public Options
717 {
718 public:
Greg Claytonf15996e2011-04-07 22:46:35 +0000719 CommandOptions (CommandInterpreter &interpreter) :
720 Options(interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000721 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000722 OptionParsingStarting();
Chris Lattner24943d22010-06-08 16:52:24 +0000723 }
724
725 virtual
726 ~CommandOptions ()
727 {
728 }
729
730 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000731 SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000732 {
733 Error error;
734 char short_option = (char) m_getopt_table[option_idx].val;
735 switch (short_option)
736 {
737 case 'f':
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000738 error = Args::StringToFormat (option_arg, m_format, &m_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +0000739 break;
740
741 case 's':
742 m_byte_size = Args::StringToUInt32 (option_arg, 0);
743 if (m_byte_size == 0)
744 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
745 break;
746
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000747 case 'i':
Greg Clayton537a7a82010-10-20 20:54:39 +0000748 m_infile.SetFile (option_arg, true);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000749 if (!m_infile.Exists())
750 {
751 m_infile.Clear();
752 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg);
753 }
754 break;
755
756 case 'o':
757 {
758 bool success;
759 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
760 if (!success)
761 {
762 error.SetErrorStringWithFormat("Invalid offset string '%s'\n", option_arg);
763 }
764 }
765 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000766
767 default:
768 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
769 break;
770 }
771 return error;
772 }
773
774 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000775 OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000776 {
Chris Lattner24943d22010-06-08 16:52:24 +0000777 m_format = eFormatBytes;
778 m_byte_size = 1;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000779 m_infile.Clear();
780 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000781 }
782
Greg Claytonb3448432011-03-24 21:19:54 +0000783 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000784 GetDefinitions ()
785 {
786 return g_option_table;
787 }
788
789 // Options table: Required for subclasses of Options.
790
Greg Claytonb3448432011-03-24 21:19:54 +0000791 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000792
793 // Instance variables to hold the values for command options.
794 lldb::Format m_format;
795 uint32_t m_byte_size;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000796 FileSpec m_infile;
797 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000798 };
799
Greg Clayton238c0a12010-09-18 01:14:36 +0000800 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
801 CommandObject (interpreter,
802 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000803 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000804 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
805 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000806 eFlagProcessMustBeLaunched),
807 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000808 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000809 CommandArgumentEntry arg1;
810 CommandArgumentEntry arg2;
811 CommandArgumentData addr_arg;
812 CommandArgumentData value_arg;
813
814 // Define the first (and only) variant of this arg.
815 addr_arg.arg_type = eArgTypeAddress;
816 addr_arg.arg_repetition = eArgRepeatPlain;
817
818 // There is only one variant this argument could be; put it into the argument entry.
819 arg1.push_back (addr_arg);
820
821 // Define the first (and only) variant of this arg.
822 value_arg.arg_type = eArgTypeValue;
823 value_arg.arg_repetition = eArgRepeatPlus;
824
825 // There is only one variant this argument could be; put it into the argument entry.
826 arg2.push_back (value_arg);
827
828 // Push the data for the first argument into the m_arguments vector.
829 m_arguments.push_back (arg1);
830 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000831 }
832
833 virtual
834 ~CommandObjectMemoryWrite ()
835 {
836 }
837
838 Options *
839 GetOptions ()
840 {
841 return &m_options;
842 }
843
844 bool
845 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
846 {
847 if (total_byte_size > 8)
848 return false;
849
850 if (total_byte_size == 8)
851 return true;
852
853 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
854 return uval64 <= max;
855 }
856
857 bool
858 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
859 {
860 if (total_byte_size > 8)
861 return false;
862
863 if (total_byte_size == 8)
864 return true;
865
866 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
867 const int64_t min = ~(max);
868 return min <= sval64 && sval64 <= max;
869 }
870
871 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000872 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000873 CommandReturnObject &result)
874 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000875 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000876 if (process == NULL)
877 {
878 result.AppendError("need a process to read memory");
879 result.SetStatus(eReturnStatusFailed);
880 return false;
881 }
882
883 const size_t argc = command.GetArgumentCount();
884
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000885 if (m_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000886 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000887 if (argc < 1)
888 {
889 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
890 result.SetStatus(eReturnStatusFailed);
891 return false;
892 }
893 }
894 else if (argc < 2)
895 {
896 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 +0000897 result.SetStatus(eReturnStatusFailed);
898 return false;
899 }
900
Chris Lattner24943d22010-06-08 16:52:24 +0000901 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000902 process->GetTarget().GetArchitecture().GetAddressByteSize(),
903 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000904
Greg Clayton54e7afa2010-07-09 20:39:50 +0000905 size_t item_byte_size = m_options.m_byte_size;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000906
Chris Lattner24943d22010-06-08 16:52:24 +0000907 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
908
909 if (addr == LLDB_INVALID_ADDRESS)
910 {
911 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
912 result.SetStatus(eReturnStatusFailed);
913 return false;
914 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000915
916 if (m_options.m_infile)
917 {
918 size_t length = SIZE_MAX;
919 if (m_options.m_byte_size > 0)
920 length = m_options.m_byte_size;
921 lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length));
922 if (data_sp)
923 {
924 length = data_sp->GetByteSize();
925 if (length > 0)
926 {
927 Error error;
928 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
929
930 if (bytes_written == length)
931 {
932 // All bytes written
933 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
934 result.SetStatus(eReturnStatusSuccessFinishResult);
935 }
936 else if (bytes_written > 0)
937 {
938 // Some byte written
939 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
940 result.SetStatus(eReturnStatusSuccessFinishResult);
941 }
942 else
943 {
944 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
945 result.SetStatus(eReturnStatusFailed);
946 }
947 }
948 }
949 else
950 {
951 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
952 result.SetStatus(eReturnStatusFailed);
953 }
954 return result.Succeeded();
955 }
956 else if (m_options.m_byte_size == 0)
957 {
958 if (m_options.m_format == eFormatPointer)
959 item_byte_size = buffer.GetAddressByteSize();
960 else
961 item_byte_size = 1;
962 }
963
Chris Lattner24943d22010-06-08 16:52:24 +0000964 command.Shift(); // shift off the address argument
965 uint64_t uval64;
966 int64_t sval64;
967 bool success = false;
968 const uint32_t num_value_args = command.GetArgumentCount();
969 uint32_t i;
970 for (i=0; i<num_value_args; ++i)
971 {
972 const char *value_str = command.GetArgumentAtIndex(i);
973
974 switch (m_options.m_format)
975 {
Greg Clayton3182eff2011-06-23 21:22:24 +0000976 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +0000977 case eFormatFloat: // TODO: add support for floats soon
978 case eFormatCharPrintable:
979 case eFormatBytesWithASCII:
980 case eFormatComplex:
981 case eFormatEnum:
982 case eFormatUnicode16:
983 case eFormatUnicode32:
984 case eFormatVectorOfChar:
985 case eFormatVectorOfSInt8:
986 case eFormatVectorOfUInt8:
987 case eFormatVectorOfSInt16:
988 case eFormatVectorOfUInt16:
989 case eFormatVectorOfSInt32:
990 case eFormatVectorOfUInt32:
991 case eFormatVectorOfSInt64:
992 case eFormatVectorOfUInt64:
993 case eFormatVectorOfFloat32:
994 case eFormatVectorOfFloat64:
995 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +0000996 case eFormatOSType:
997 case eFormatComplexInteger:
Chris Lattner24943d22010-06-08 16:52:24 +0000998 result.AppendError("unsupported format for writing memory");
999 result.SetStatus(eReturnStatusFailed);
1000 return false;
1001
1002 case eFormatDefault:
1003 case eFormatBytes:
1004 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001005 case eFormatPointer:
1006
Chris Lattner24943d22010-06-08 16:52:24 +00001007 // Decode hex bytes
1008 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1009 if (!success)
1010 {
1011 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1012 result.SetStatus(eReturnStatusFailed);
1013 return false;
1014 }
1015 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1016 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001017 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001018 result.SetStatus(eReturnStatusFailed);
1019 return false;
1020 }
1021 buffer.PutMaxHex64 (uval64, item_byte_size);
1022 break;
1023
1024 case eFormatBoolean:
1025 uval64 = Args::StringToBoolean(value_str, false, &success);
1026 if (!success)
1027 {
1028 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1029 result.SetStatus(eReturnStatusFailed);
1030 return false;
1031 }
1032 buffer.PutMaxHex64 (uval64, item_byte_size);
1033 break;
1034
1035 case eFormatBinary:
1036 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1037 if (!success)
1038 {
1039 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1040 result.SetStatus(eReturnStatusFailed);
1041 return false;
1042 }
1043 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1044 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001045 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001046 result.SetStatus(eReturnStatusFailed);
1047 return false;
1048 }
1049 buffer.PutMaxHex64 (uval64, item_byte_size);
1050 break;
1051
Greg Clayton307fa072011-06-17 23:50:44 +00001052 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001053 case eFormatChar:
1054 case eFormatCString:
1055 if (value_str[0])
1056 {
1057 size_t len = strlen (value_str);
1058 // Include the NULL for C strings...
1059 if (m_options.m_format == eFormatCString)
1060 ++len;
1061 Error error;
1062 if (process->WriteMemory (addr, value_str, len, error) == len)
1063 {
1064 addr += len;
1065 }
1066 else
1067 {
1068 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1069 result.SetStatus(eReturnStatusFailed);
1070 return false;
1071 }
1072 }
1073 break;
1074
1075 case eFormatDecimal:
1076 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1077 if (!success)
1078 {
1079 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1080 result.SetStatus(eReturnStatusFailed);
1081 return false;
1082 }
1083 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1084 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001085 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001086 result.SetStatus(eReturnStatusFailed);
1087 return false;
1088 }
1089 buffer.PutMaxHex64 (sval64, item_byte_size);
1090 break;
1091
1092 case eFormatUnsigned:
1093 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1094 if (!success)
1095 {
1096 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1097 result.SetStatus(eReturnStatusFailed);
1098 return false;
1099 }
1100 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1101 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001102 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001103 result.SetStatus(eReturnStatusFailed);
1104 return false;
1105 }
1106 buffer.PutMaxHex64 (uval64, item_byte_size);
1107 break;
1108
1109 case eFormatOctal:
1110 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1111 if (!success)
1112 {
1113 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1114 result.SetStatus(eReturnStatusFailed);
1115 return false;
1116 }
1117 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1118 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001119 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001120 result.SetStatus(eReturnStatusFailed);
1121 return false;
1122 }
1123 buffer.PutMaxHex64 (uval64, item_byte_size);
1124 break;
1125 }
1126 }
1127
1128 if (!buffer.GetString().empty())
1129 {
1130 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001131 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001132 return true;
1133 else
1134 {
1135 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1136 result.SetStatus(eReturnStatusFailed);
1137 return false;
1138 }
1139 }
1140 return true;
1141 }
1142
1143protected:
1144 CommandOptions m_options;
1145};
1146
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001147#define SET1 LLDB_OPT_SET_1
1148#define SET2 LLDB_OPT_SET_2
1149
Greg Claytonb3448432011-03-24 21:19:54 +00001150OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +00001151CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
1152{
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001153{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."},
1154{ SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."},
1155{ SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1156{ SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
1157{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +00001158};
1159
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001160#undef SET1
1161#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +00001162
1163//-------------------------------------------------------------------------
1164// CommandObjectMemory
1165//-------------------------------------------------------------------------
1166
Greg Clayton63094e02010-06-23 01:19:29 +00001167CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001168 CommandObjectMultiword (interpreter,
1169 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001170 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001171 "memory <subcommand> [<subcommand-options>]")
1172{
Greg Clayton238c0a12010-09-18 01:14:36 +00001173 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1174 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001175}
1176
1177CommandObjectMemory::~CommandObjectMemory ()
1178{
1179}