blob: cf9ecb01aaba174f7343541f40f573ff59d0b9aa [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"
Sean Callanan3e80cd92011-10-12 02:08:07 +000028#include "lldb/Symbol/ClangNamespaceDecl.h"
Chris Lattner24943d22010-06-08 16:52:24 +000029#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000030#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000031
32using namespace lldb;
33using namespace lldb_private;
34
Greg Clayton56bbdaf2011-04-28 20:55:26 +000035static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000036g_option_table[] =
37{
Greg Clayton57b3c6b2011-04-27 22:04:39 +000038 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
39 { 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."},
40 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
41};
42
43
44
45class OptionGroupReadMemory : public OptionGroup
46{
47public:
48
49 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000050 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000051 m_output_as_binary (false),
52 m_view_as_type()
53 {
54 }
55
56 virtual
57 ~OptionGroupReadMemory ()
58 {
59 }
60
61
62 virtual uint32_t
63 GetNumDefinitions ()
64 {
65 return sizeof (g_option_table) / sizeof (OptionDefinition);
66 }
67
68 virtual const OptionDefinition*
69 GetDefinitions ()
70 {
71 return g_option_table;
72 }
73
74 virtual Error
75 SetOptionValue (CommandInterpreter &interpreter,
76 uint32_t option_idx,
77 const char *option_arg)
78 {
79 Error error;
80 char short_option = (char) g_option_table[option_idx].short_option;
81
82 switch (short_option)
83 {
84 case 'l':
85 error = m_num_per_line.SetValueFromCString (option_arg);
86 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000087 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000088 break;
Greg Claytona42880a2011-10-25 06:44:01 +000089
Greg Clayton57b3c6b2011-04-27 22:04:39 +000090 case 'b':
91 m_output_as_binary = true;
92 break;
93
94 case 't':
95 error = m_view_as_type.SetValueFromCString (option_arg);
96 break;
97
98 default:
Greg Clayton9c236732011-10-26 00:56:27 +000099 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000100 break;
101 }
102 return error;
103 }
104
105 virtual void
106 OptionParsingStarting (CommandInterpreter &interpreter)
107 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000108 m_num_per_line.Clear();
109 m_output_as_binary = false;
110 m_view_as_type.Clear();
111 }
112
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000113 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000114 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000115 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000116 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000117 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
118 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000119 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000120 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000121 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000122
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000123 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000124 {
125 default:
126 break;
127
128 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000129 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000130 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000131 if (!num_per_line_option_set)
132 m_num_per_line = 1;
133 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000134 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000135 break;
136
137 case eFormatCString:
138 break;
139
140 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000141 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000142 if (!num_per_line_option_set)
143 m_num_per_line = 4;
144 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000145 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000146 break;
147
148 case eFormatBinary:
149 case eFormatFloat:
150 case eFormatOctal:
151 case eFormatDecimal:
152 case eFormatEnum:
153 case eFormatUnicode16:
154 case eFormatUnicode32:
155 case eFormatUnsigned:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000156 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000157 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000158 if (!num_per_line_option_set)
159 m_num_per_line = 1;
160 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000161 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000162 break;
163
164 case eFormatBytes:
165 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000166 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000167 {
Greg Claytona42880a2011-10-25 06:44:01 +0000168 if (byte_size_value > 1)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000169 error.SetErrorString ("use --count option to specify an end address to display a number of bytes");
170 }
171 else
Greg Claytona42880a2011-10-25 06:44:01 +0000172 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000173 if (!num_per_line_option_set)
174 m_num_per_line = 16;
175 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000176 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000177 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000178 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000179 case eFormatChar:
180 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000181 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000182 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000183 if (!num_per_line_option_set)
184 m_num_per_line = 32;
185 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000186 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000187 break;
188 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000189 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000190 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000191 if (!num_per_line_option_set)
192 m_num_per_line = 1;
193 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000194 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000195 break;
196 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000197 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000198 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000199 if (!num_per_line_option_set)
200 {
Greg Claytona42880a2011-10-25 06:44:01 +0000201 switch (byte_size_value)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000202 {
203 case 1:
204 case 2:
205 m_num_per_line = 8;
206 break;
207 case 4:
208 m_num_per_line = 4;
209 break;
210 case 8:
211 m_num_per_line = 2;
212 break;
213 default:
214 m_num_per_line = 1;
215 break;
216 }
217 }
218 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000219 count_value = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000220 break;
221
222 case eFormatVectorOfChar:
223 case eFormatVectorOfSInt8:
224 case eFormatVectorOfUInt8:
225 case eFormatVectorOfSInt16:
226 case eFormatVectorOfUInt16:
227 case eFormatVectorOfSInt32:
228 case eFormatVectorOfUInt32:
229 case eFormatVectorOfSInt64:
230 case eFormatVectorOfUInt64:
231 case eFormatVectorOfFloat32:
232 case eFormatVectorOfFloat64:
233 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000234 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000235 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000236 if (!num_per_line_option_set)
237 m_num_per_line = 1;
238 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000239 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000240 break;
241 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000242 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000243 }
244
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000245 OptionValueUInt64 m_num_per_line;
246 bool m_output_as_binary;
247 OptionValueString m_view_as_type;
248};
249
250
251
Chris Lattner24943d22010-06-08 16:52:24 +0000252//----------------------------------------------------------------------
253// Read memory from the inferior process
254//----------------------------------------------------------------------
255class CommandObjectMemoryRead : public CommandObject
256{
257public:
258
Greg Clayton238c0a12010-09-18 01:14:36 +0000259 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
260 CommandObject (interpreter,
261 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000262 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000263 NULL,
Jim Ingham8cc3f692011-07-09 00:55:34 +0000264 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000265 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000266 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000267 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000268 m_outfile_options (),
269 m_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000270 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000271 CommandArgumentEntry arg1;
272 CommandArgumentEntry arg2;
273 CommandArgumentData start_addr_arg;
274 CommandArgumentData end_addr_arg;
275
276 // Define the first (and only) variant of this arg.
277 start_addr_arg.arg_type = eArgTypeStartAddress;
278 start_addr_arg.arg_repetition = eArgRepeatPlain;
279
280 // There is only one variant this argument could be; put it into the argument entry.
281 arg1.push_back (start_addr_arg);
282
283 // Define the first (and only) variant of this arg.
284 end_addr_arg.arg_type = eArgTypeEndAddress;
285 end_addr_arg.arg_repetition = eArgRepeatOptional;
286
287 // There is only one variant this argument could be; put it into the argument entry.
288 arg2.push_back (end_addr_arg);
289
290 // Push the data for the first argument into the m_arguments vector.
291 m_arguments.push_back (arg1);
292 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000293
Greg Claytona42880a2011-10-25 06:44:01 +0000294 // Add the "--format" and "--count" options to group 1 and 3
295 m_option_group.Append (&m_format_options,
296 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
297 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
298 // Add the "--size" option to group 1 and 2
299 m_option_group.Append (&m_format_options,
300 OptionGroupFormat::OPTION_GROUP_SIZE,
301 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000302 m_option_group.Append (&m_memory_options);
303 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 +0000304 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000305 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000306 }
307
308 virtual
309 ~CommandObjectMemoryRead ()
310 {
311 }
312
313 Options *
314 GetOptions ()
315 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000316 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000317 }
318
319 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000320 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000321 CommandReturnObject &result)
322 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000323 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000324 Target *target = exe_ctx.GetTargetPtr();
325 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000326 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000327 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000328 result.SetStatus(eReturnStatusFailed);
329 return false;
330 }
331 const size_t argc = command.GetArgumentCount();
332
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000333
Chris Lattner24943d22010-06-08 16:52:24 +0000334 if (argc == 0 || argc > 2)
335 {
336 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
337 result.SetStatus(eReturnStatusFailed);
338 return false;
339 }
340
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000341 ClangASTType clang_ast_type;
342 Error error;
343
344 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000345 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
346 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000347 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000348 // We are viewing memory as a type
349 SymbolContext sc;
350 const bool append = true;
351 TypeList type_list;
352 uint32_t reference_count = 0;
353 uint32_t pointer_count = 0;
354 size_t idx;
355 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
356 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
357 std::string type_str(view_as_type_cstr);
358
359 // Remove all instances of g_keywords that are followed by spaces
360 for (size_t i = 0; i < g_num_keywords; ++i)
361 {
362 const char *keyword = g_keywords[i];
363 int keyword_len = ::strlen (keyword);
364 while ((idx = type_str.find (keyword)) != std::string::npos)
365 {
366 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
367 type_str.erase(idx, keyword_len+1);
368 }
369 }
370 bool done = type_str.empty();
371 //
372 idx = type_str.find_first_not_of (" \t");
373 if (idx > 0 && idx != std::string::npos)
374 type_str.erase (0, idx);
375 while (!done)
376 {
377 // Strip trailing spaces
378 if (type_str.empty())
379 done = true;
380 else
381 {
382 switch (type_str[type_str.size()-1])
383 {
384 case '*':
385 ++pointer_count;
386 // fall through...
387 case ' ':
388 case '\t':
389 type_str.erase(type_str.size()-1);
390 break;
391
392 case '&':
393 if (reference_count == 0)
394 {
395 reference_count = 1;
396 type_str.erase(type_str.size()-1);
397 }
398 else
399 {
400 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
401 result.SetStatus(eReturnStatusFailed);
402 return false;
403 }
404 break;
405
406 default:
407 done = true;
408 break;
409 }
410 }
411 }
412
413 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000414 StackFrame *frame = exe_ctx.GetFramePtr();
415 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000416 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000417 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000418 if (sc.module_sp)
419 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000420 sc.module_sp->FindTypes (sc,
421 lookup_type_name,
422 NULL,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000423 append,
424 1,
425 type_list);
426 }
427 }
428 if (type_list.GetSize() == 0)
429 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000430 target->GetImages().FindTypes (sc,
431 lookup_type_name,
432 append,
433 1,
434 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000435 }
436
437 if (type_list.GetSize() == 0)
438 {
439 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
440 lookup_type_name.GetCString(),
441 view_as_type_cstr);
442 result.SetStatus(eReturnStatusFailed);
443 return false;
444 }
445
446 TypeSP type_sp (type_list.GetTypeAtIndex(0));
447 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
448
449 while (pointer_count > 0)
450 {
451 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
452 if (pointer_type)
453 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
454 else
455 {
456 result.AppendError ("unable make a pointer type\n");
457 result.SetStatus(eReturnStatusFailed);
458 return false;
459 }
460 --pointer_count;
461 }
462
Greg Claytona42880a2011-10-25 06:44:01 +0000463 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000464
Greg Claytona42880a2011-10-25 06:44:01 +0000465 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000466 {
467 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
468 view_as_type_cstr);
469 result.SetStatus(eReturnStatusFailed);
470 return false;
471 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000472
Greg Claytona42880a2011-10-25 06:44:01 +0000473 if (!m_format_options.GetCountValue().OptionWasSet())
474 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000475 }
476 else
477 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000478 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000479 }
480
481 // Look for invalid combinations of settings
482 if (error.Fail())
483 {
484 result.AppendErrorWithFormat("%s", error.AsCString());
485 result.SetStatus(eReturnStatusFailed);
486 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000487 }
488
Greg Claytona42880a2011-10-25 06:44:01 +0000489 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
490 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000491 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000492
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000493 size_t total_byte_size = item_count * item_byte_size;
Chris Lattner24943d22010-06-08 16:52:24 +0000494 if (total_byte_size == 0)
495 total_byte_size = 32;
496
497 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
498
499 if (addr == LLDB_INVALID_ADDRESS)
500 {
501 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
502 result.SetStatus(eReturnStatusFailed);
503 return false;
504 }
505
506 if (argc == 2)
507 {
508 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
509 if (end_addr == LLDB_INVALID_ADDRESS)
510 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000511 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000512 result.SetStatus(eReturnStatusFailed);
513 return false;
514 }
515 else if (end_addr <= addr)
516 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000517 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 +0000518 result.SetStatus(eReturnStatusFailed);
519 return false;
520 }
Greg Claytona42880a2011-10-25 06:44:01 +0000521 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000522 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000523 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 +0000524 result.SetStatus(eReturnStatusFailed);
525 return false;
526 }
527
528 total_byte_size = end_addr - addr;
529 item_count = total_byte_size / item_byte_size;
530 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000531
532 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000533 size_t bytes_read = 0;
534 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000535 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000536 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Jim Ingham8cc3f692011-07-09 00:55:34 +0000537 Address address(NULL, addr);
Greg Clayton567e7f32011-09-22 04:58:26 +0000538 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000539 if (bytes_read == 0)
540 {
541 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
542 result.AppendError(error.AsCString());
543 result.SetStatus(eReturnStatusFailed);
544 return false;
545 }
546
547 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000548 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 +0000549 }
550
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000551 StreamFile outfile_stream;
552 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000553 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
554 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000555 {
556 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000557 outfile_spec.GetPath (path, sizeof(path));
558
559 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
560 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
561 if (append)
562 open_options |= File::eOpenOptionAppend;
563
564 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000565 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000566 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000567 {
568 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
569 if (bytes_written > 0)
570 {
571 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
572 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000573 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000574 path);
575 return true;
576 }
577 else
578 {
579 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
580 result.SetStatus(eReturnStatusFailed);
581 return false;
582 }
583 }
584 else
585 {
586 // We are going to write ASCII to the file just point the
587 // output_stream to our outfile_stream...
588 output_stream = &outfile_stream;
589 }
590 }
591 else
592 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000593 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000594 result.SetStatus(eReturnStatusFailed);
595 return false;
596 }
597 }
598 else
599 {
600 output_stream = &result.GetOutputStream();
601 }
602
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000603
604 if (clang_ast_type.GetOpaqueQualType())
605 {
606 for (uint32_t i = 0; i<item_count; ++i)
607 {
608 addr_t item_addr = addr + (i * item_byte_size);
609 Address address (NULL, item_addr);
610 StreamString name_strm;
611 name_strm.Printf ("0x%llx", item_addr);
612 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
613 name_strm.GetString().c_str(),
614 address,
615 clang_ast_type));
616 if (valobj_sp)
617 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000618 if (format != eFormatDefault)
619 valobj_sp->SetFormat (format);
620
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000621 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000622
623 ValueObject::DumpValueObject (*output_stream,
624 valobj_sp.get(),
625 NULL,
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000626 m_varobj_options.ptr_depth,
627 0,
628 m_varobj_options.max_depth,
629 m_varobj_options.show_types,
630 m_varobj_options.show_location,
631 m_varobj_options.use_objc,
Jim Ingham10de7d12011-05-04 03:43:18 +0000632 m_varobj_options.use_dynamic,
Enrico Granata840eb262011-08-09 23:50:01 +0000633 m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000634 scope_already_checked,
Enrico Granata7f163b32011-07-16 01:22:04 +0000635 m_varobj_options.flat_output,
Enrico Granata018921d2011-08-12 02:00:06 +0000636 m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth,
637 m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000638 }
639 else
640 {
641 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
642 view_as_type_cstr,
643 name_strm.GetString().c_str());
644 result.SetStatus(eReturnStatusFailed);
645 return false;
646 }
647 }
648 return true;
649 }
650
651 result.SetStatus(eReturnStatusSuccessFinishResult);
652 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000653 target->GetArchitecture().GetByteOrder(),
654 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000655
656
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000657 assert (output_stream);
658 data.Dump (output_stream,
659 0,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000660 m_format_options.GetFormat(),
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000661 item_byte_size,
662 item_count,
663 num_per_line,
664 addr,
665 0,
666 0);
667 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000668 return true;
669 }
670
671protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000672 OptionGroupOptions m_option_group;
673 OptionGroupFormat m_format_options;
674 OptionGroupReadMemory m_memory_options;
675 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000676 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000677
Chris Lattner24943d22010-06-08 16:52:24 +0000678};
679
Greg Claytona42880a2011-10-25 06:44:01 +0000680
681OptionDefinition
682g_memory_write_option_table[] =
683{
684{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
685{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
686};
687
688
Chris Lattner24943d22010-06-08 16:52:24 +0000689//----------------------------------------------------------------------
690// Write memory to the inferior process
691//----------------------------------------------------------------------
692class CommandObjectMemoryWrite : public CommandObject
693{
694public:
695
Greg Claytona42880a2011-10-25 06:44:01 +0000696 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000697 {
698 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000699 OptionGroupWriteMemory () :
700 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000701 {
Chris Lattner24943d22010-06-08 16:52:24 +0000702 }
703
704 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000705 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000706 {
707 }
708
Greg Claytona42880a2011-10-25 06:44:01 +0000709 virtual uint32_t
710 GetNumDefinitions ()
711 {
712 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
713 }
714
715 virtual const OptionDefinition*
716 GetDefinitions ()
717 {
718 return g_memory_write_option_table;
719 }
720
Chris Lattner24943d22010-06-08 16:52:24 +0000721 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000722 SetOptionValue (CommandInterpreter &interpreter,
723 uint32_t option_idx,
724 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000725 {
726 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000727 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
728
Chris Lattner24943d22010-06-08 16:52:24 +0000729 switch (short_option)
730 {
Greg Claytona42880a2011-10-25 06:44:01 +0000731 case 'i':
732 m_infile.SetFile (option_arg, true);
733 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000734 {
Greg Claytona42880a2011-10-25 06:44:01 +0000735 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000736 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000737 }
Greg Claytona42880a2011-10-25 06:44:01 +0000738 break;
739
740 case 'o':
741 {
742 bool success;
743 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
744 if (!success)
745 {
Greg Clayton9c236732011-10-26 00:56:27 +0000746 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000747 }
748 }
749 break;
750
751 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000752 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000753 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000754 }
755 return error;
756 }
Greg Claytona42880a2011-10-25 06:44:01 +0000757
758 virtual void
759 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000760 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000761 m_infile.Clear();
762 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000763 }
764
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000765 FileSpec m_infile;
766 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000767 };
768
Greg Clayton238c0a12010-09-18 01:14:36 +0000769 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
770 CommandObject (interpreter,
771 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000772 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000773 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
774 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000775 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000776 m_option_group (interpreter),
777 m_format_options (eFormatBytes, 1, UINT64_MAX),
778 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000779 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000780 CommandArgumentEntry arg1;
781 CommandArgumentEntry arg2;
782 CommandArgumentData addr_arg;
783 CommandArgumentData value_arg;
784
785 // Define the first (and only) variant of this arg.
786 addr_arg.arg_type = eArgTypeAddress;
787 addr_arg.arg_repetition = eArgRepeatPlain;
788
789 // There is only one variant this argument could be; put it into the argument entry.
790 arg1.push_back (addr_arg);
791
792 // Define the first (and only) variant of this arg.
793 value_arg.arg_type = eArgTypeValue;
794 value_arg.arg_repetition = eArgRepeatPlus;
795
796 // There is only one variant this argument could be; put it into the argument entry.
797 arg2.push_back (value_arg);
798
799 // Push the data for the first argument into the m_arguments vector.
800 m_arguments.push_back (arg1);
801 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000802
803 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
804 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
805 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
806 m_option_group.Finalize();
807
Chris Lattner24943d22010-06-08 16:52:24 +0000808 }
809
810 virtual
811 ~CommandObjectMemoryWrite ()
812 {
813 }
814
815 Options *
816 GetOptions ()
817 {
Greg Claytona42880a2011-10-25 06:44:01 +0000818 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000819 }
820
821 bool
822 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
823 {
824 if (total_byte_size > 8)
825 return false;
826
827 if (total_byte_size == 8)
828 return true;
829
830 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
831 return uval64 <= max;
832 }
833
834 bool
835 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
836 {
837 if (total_byte_size > 8)
838 return false;
839
840 if (total_byte_size == 8)
841 return true;
842
843 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
844 const int64_t min = ~(max);
845 return min <= sval64 && sval64 <= max;
846 }
847
848 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000849 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000850 CommandReturnObject &result)
851 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000852 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000853 if (process == NULL)
854 {
855 result.AppendError("need a process to read memory");
856 result.SetStatus(eReturnStatusFailed);
857 return false;
858 }
859
860 const size_t argc = command.GetArgumentCount();
861
Greg Claytona42880a2011-10-25 06:44:01 +0000862 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000863 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000864 if (argc < 1)
865 {
866 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
867 result.SetStatus(eReturnStatusFailed);
868 return false;
869 }
870 }
871 else if (argc < 2)
872 {
873 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 +0000874 result.SetStatus(eReturnStatusFailed);
875 return false;
876 }
877
Chris Lattner24943d22010-06-08 16:52:24 +0000878 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000879 process->GetTarget().GetArchitecture().GetAddressByteSize(),
880 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000881
Greg Claytona42880a2011-10-25 06:44:01 +0000882 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
883 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000884
Chris Lattner24943d22010-06-08 16:52:24 +0000885 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
886
887 if (addr == LLDB_INVALID_ADDRESS)
888 {
889 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
890 result.SetStatus(eReturnStatusFailed);
891 return false;
892 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000893
Greg Claytona42880a2011-10-25 06:44:01 +0000894 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000895 {
896 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000897 if (item_byte_size > 0)
898 length = item_byte_size;
899 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000900 if (data_sp)
901 {
902 length = data_sp->GetByteSize();
903 if (length > 0)
904 {
905 Error error;
906 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
907
908 if (bytes_written == length)
909 {
910 // All bytes written
911 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
912 result.SetStatus(eReturnStatusSuccessFinishResult);
913 }
914 else if (bytes_written > 0)
915 {
916 // Some byte written
917 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
918 result.SetStatus(eReturnStatusSuccessFinishResult);
919 }
920 else
921 {
922 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
923 result.SetStatus(eReturnStatusFailed);
924 }
925 }
926 }
927 else
928 {
929 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
930 result.SetStatus(eReturnStatusFailed);
931 }
932 return result.Succeeded();
933 }
Greg Claytona42880a2011-10-25 06:44:01 +0000934 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000935 {
Greg Claytona42880a2011-10-25 06:44:01 +0000936 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000937 item_byte_size = buffer.GetAddressByteSize();
938 else
939 item_byte_size = 1;
940 }
941
Chris Lattner24943d22010-06-08 16:52:24 +0000942 command.Shift(); // shift off the address argument
943 uint64_t uval64;
944 int64_t sval64;
945 bool success = false;
946 const uint32_t num_value_args = command.GetArgumentCount();
947 uint32_t i;
948 for (i=0; i<num_value_args; ++i)
949 {
950 const char *value_str = command.GetArgumentAtIndex(i);
951
Greg Claytona42880a2011-10-25 06:44:01 +0000952 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +0000953 {
Greg Clayton3182eff2011-06-23 21:22:24 +0000954 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +0000955 case eFormatFloat: // TODO: add support for floats soon
956 case eFormatCharPrintable:
957 case eFormatBytesWithASCII:
958 case eFormatComplex:
959 case eFormatEnum:
960 case eFormatUnicode16:
961 case eFormatUnicode32:
962 case eFormatVectorOfChar:
963 case eFormatVectorOfSInt8:
964 case eFormatVectorOfUInt8:
965 case eFormatVectorOfSInt16:
966 case eFormatVectorOfUInt16:
967 case eFormatVectorOfSInt32:
968 case eFormatVectorOfUInt32:
969 case eFormatVectorOfSInt64:
970 case eFormatVectorOfUInt64:
971 case eFormatVectorOfFloat32:
972 case eFormatVectorOfFloat64:
973 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +0000974 case eFormatOSType:
975 case eFormatComplexInteger:
Chris Lattner24943d22010-06-08 16:52:24 +0000976 result.AppendError("unsupported format for writing memory");
977 result.SetStatus(eReturnStatusFailed);
978 return false;
979
980 case eFormatDefault:
981 case eFormatBytes:
982 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +0000983 case eFormatPointer:
984
Chris Lattner24943d22010-06-08 16:52:24 +0000985 // Decode hex bytes
986 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
987 if (!success)
988 {
989 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
990 result.SetStatus(eReturnStatusFailed);
991 return false;
992 }
993 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
994 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000995 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 +0000996 result.SetStatus(eReturnStatusFailed);
997 return false;
998 }
999 buffer.PutMaxHex64 (uval64, item_byte_size);
1000 break;
1001
1002 case eFormatBoolean:
1003 uval64 = Args::StringToBoolean(value_str, false, &success);
1004 if (!success)
1005 {
1006 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1007 result.SetStatus(eReturnStatusFailed);
1008 return false;
1009 }
1010 buffer.PutMaxHex64 (uval64, item_byte_size);
1011 break;
1012
1013 case eFormatBinary:
1014 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1015 if (!success)
1016 {
1017 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1018 result.SetStatus(eReturnStatusFailed);
1019 return false;
1020 }
1021 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1022 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001023 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 +00001024 result.SetStatus(eReturnStatusFailed);
1025 return false;
1026 }
1027 buffer.PutMaxHex64 (uval64, item_byte_size);
1028 break;
1029
Greg Clayton307fa072011-06-17 23:50:44 +00001030 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001031 case eFormatChar:
1032 case eFormatCString:
1033 if (value_str[0])
1034 {
1035 size_t len = strlen (value_str);
1036 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001037 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001038 ++len;
1039 Error error;
1040 if (process->WriteMemory (addr, value_str, len, error) == len)
1041 {
1042 addr += len;
1043 }
1044 else
1045 {
1046 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1047 result.SetStatus(eReturnStatusFailed);
1048 return false;
1049 }
1050 }
1051 break;
1052
1053 case eFormatDecimal:
1054 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1055 if (!success)
1056 {
1057 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1058 result.SetStatus(eReturnStatusFailed);
1059 return false;
1060 }
1061 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1062 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001063 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 +00001064 result.SetStatus(eReturnStatusFailed);
1065 return false;
1066 }
1067 buffer.PutMaxHex64 (sval64, item_byte_size);
1068 break;
1069
1070 case eFormatUnsigned:
1071 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1072 if (!success)
1073 {
1074 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1075 result.SetStatus(eReturnStatusFailed);
1076 return false;
1077 }
1078 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1079 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001080 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 +00001081 result.SetStatus(eReturnStatusFailed);
1082 return false;
1083 }
1084 buffer.PutMaxHex64 (uval64, item_byte_size);
1085 break;
1086
1087 case eFormatOctal:
1088 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1089 if (!success)
1090 {
1091 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1092 result.SetStatus(eReturnStatusFailed);
1093 return false;
1094 }
1095 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1096 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001097 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 +00001098 result.SetStatus(eReturnStatusFailed);
1099 return false;
1100 }
1101 buffer.PutMaxHex64 (uval64, item_byte_size);
1102 break;
1103 }
1104 }
1105
1106 if (!buffer.GetString().empty())
1107 {
1108 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001109 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001110 return true;
1111 else
1112 {
1113 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1114 result.SetStatus(eReturnStatusFailed);
1115 return false;
1116 }
1117 }
1118 return true;
1119 }
1120
1121protected:
Greg Claytona42880a2011-10-25 06:44:01 +00001122
1123 OptionGroupOptions m_option_group;
1124 OptionGroupFormat m_format_options;
1125 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001126};
1127
Chris Lattner24943d22010-06-08 16:52:24 +00001128
1129//-------------------------------------------------------------------------
1130// CommandObjectMemory
1131//-------------------------------------------------------------------------
1132
Greg Clayton63094e02010-06-23 01:19:29 +00001133CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001134 CommandObjectMultiword (interpreter,
1135 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001136 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001137 "memory <subcommand> [<subcommand-options>]")
1138{
Greg Clayton238c0a12010-09-18 01:14:36 +00001139 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1140 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001141}
1142
1143CommandObjectMemory::~CommandObjectMemory ()
1144{
1145}