blob: 63aa1108785a13e8773bcf4c58d5008b711bb026 [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 Clayton902b5be2011-10-26 04:32:38 +0000245 bool
246 AnyOptionWasSet () const
247 {
248 return m_num_per_line.OptionWasSet() ||
249 m_output_as_binary ||
250 m_view_as_type.OptionWasSet();
251 }
252
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000253 OptionValueUInt64 m_num_per_line;
254 bool m_output_as_binary;
255 OptionValueString m_view_as_type;
256};
257
258
259
Chris Lattner24943d22010-06-08 16:52:24 +0000260//----------------------------------------------------------------------
261// Read memory from the inferior process
262//----------------------------------------------------------------------
263class CommandObjectMemoryRead : public CommandObject
264{
265public:
266
Greg Clayton238c0a12010-09-18 01:14:36 +0000267 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
268 CommandObject (interpreter,
269 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000270 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000271 NULL,
Jim Ingham8cc3f692011-07-09 00:55:34 +0000272 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000273 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000274 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000275 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000276 m_outfile_options (),
Greg Clayton902b5be2011-10-26 04:32:38 +0000277 m_varobj_options(),
278 m_next_addr(LLDB_INVALID_ADDRESS),
279 m_prev_byte_size(0),
280 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
281 m_prev_memory_options (),
282 m_prev_outfile_options (),
283 m_prev_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000284 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000285 CommandArgumentEntry arg1;
286 CommandArgumentEntry arg2;
287 CommandArgumentData start_addr_arg;
288 CommandArgumentData end_addr_arg;
289
290 // Define the first (and only) variant of this arg.
291 start_addr_arg.arg_type = eArgTypeStartAddress;
292 start_addr_arg.arg_repetition = eArgRepeatPlain;
293
294 // There is only one variant this argument could be; put it into the argument entry.
295 arg1.push_back (start_addr_arg);
296
297 // Define the first (and only) variant of this arg.
298 end_addr_arg.arg_type = eArgTypeEndAddress;
299 end_addr_arg.arg_repetition = eArgRepeatOptional;
300
301 // There is only one variant this argument could be; put it into the argument entry.
302 arg2.push_back (end_addr_arg);
303
304 // Push the data for the first argument into the m_arguments vector.
305 m_arguments.push_back (arg1);
306 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000307
Greg Claytona42880a2011-10-25 06:44:01 +0000308 // Add the "--format" and "--count" options to group 1 and 3
309 m_option_group.Append (&m_format_options,
310 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
311 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
312 // Add the "--size" option to group 1 and 2
313 m_option_group.Append (&m_format_options,
314 OptionGroupFormat::OPTION_GROUP_SIZE,
315 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000316 m_option_group.Append (&m_memory_options);
317 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 +0000318 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000319 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000320 }
321
322 virtual
323 ~CommandObjectMemoryRead ()
324 {
325 }
326
327 Options *
328 GetOptions ()
329 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000330 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000331 }
332
Greg Clayton902b5be2011-10-26 04:32:38 +0000333 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
334 {
335 return m_cmd_name.c_str();
336 }
337
Chris Lattner24943d22010-06-08 16:52:24 +0000338 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000339 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000340 CommandReturnObject &result)
341 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000342 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000343 Target *target = exe_ctx.GetTargetPtr();
344 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000345 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000346 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000347 result.SetStatus(eReturnStatusFailed);
348 return false;
349 }
350 const size_t argc = command.GetArgumentCount();
351
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000352
Greg Clayton902b5be2011-10-26 04:32:38 +0000353 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000354 {
355 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
356 result.SetStatus(eReturnStatusFailed);
357 return false;
358 }
359
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000360 ClangASTType clang_ast_type;
361 Error error;
362
363 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000364 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
365 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000366 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000367 // We are viewing memory as a type
368 SymbolContext sc;
369 const bool append = true;
370 TypeList type_list;
371 uint32_t reference_count = 0;
372 uint32_t pointer_count = 0;
373 size_t idx;
374 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
375 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
376 std::string type_str(view_as_type_cstr);
377
378 // Remove all instances of g_keywords that are followed by spaces
379 for (size_t i = 0; i < g_num_keywords; ++i)
380 {
381 const char *keyword = g_keywords[i];
382 int keyword_len = ::strlen (keyword);
383 while ((idx = type_str.find (keyword)) != std::string::npos)
384 {
385 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
386 type_str.erase(idx, keyword_len+1);
387 }
388 }
389 bool done = type_str.empty();
390 //
391 idx = type_str.find_first_not_of (" \t");
392 if (idx > 0 && idx != std::string::npos)
393 type_str.erase (0, idx);
394 while (!done)
395 {
396 // Strip trailing spaces
397 if (type_str.empty())
398 done = true;
399 else
400 {
401 switch (type_str[type_str.size()-1])
402 {
403 case '*':
404 ++pointer_count;
405 // fall through...
406 case ' ':
407 case '\t':
408 type_str.erase(type_str.size()-1);
409 break;
410
411 case '&':
412 if (reference_count == 0)
413 {
414 reference_count = 1;
415 type_str.erase(type_str.size()-1);
416 }
417 else
418 {
419 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
420 result.SetStatus(eReturnStatusFailed);
421 return false;
422 }
423 break;
424
425 default:
426 done = true;
427 break;
428 }
429 }
430 }
431
432 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000433 StackFrame *frame = exe_ctx.GetFramePtr();
434 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000435 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000436 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000437 if (sc.module_sp)
438 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000439 sc.module_sp->FindTypes (sc,
440 lookup_type_name,
441 NULL,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000442 append,
443 1,
444 type_list);
445 }
446 }
447 if (type_list.GetSize() == 0)
448 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000449 target->GetImages().FindTypes (sc,
450 lookup_type_name,
451 append,
452 1,
453 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000454 }
455
456 if (type_list.GetSize() == 0)
457 {
458 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
459 lookup_type_name.GetCString(),
460 view_as_type_cstr);
461 result.SetStatus(eReturnStatusFailed);
462 return false;
463 }
464
465 TypeSP type_sp (type_list.GetTypeAtIndex(0));
466 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
467
468 while (pointer_count > 0)
469 {
470 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
471 if (pointer_type)
472 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
473 else
474 {
475 result.AppendError ("unable make a pointer type\n");
476 result.SetStatus(eReturnStatusFailed);
477 return false;
478 }
479 --pointer_count;
480 }
481
Greg Claytona42880a2011-10-25 06:44:01 +0000482 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000483
Greg Claytona42880a2011-10-25 06:44:01 +0000484 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000485 {
486 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
487 view_as_type_cstr);
488 result.SetStatus(eReturnStatusFailed);
489 return false;
490 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000491
Greg Claytona42880a2011-10-25 06:44:01 +0000492 if (!m_format_options.GetCountValue().OptionWasSet())
493 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000494 }
495 else
496 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000497 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000498 }
499
500 // Look for invalid combinations of settings
501 if (error.Fail())
502 {
503 result.AppendErrorWithFormat("%s", error.AsCString());
504 result.SetStatus(eReturnStatusFailed);
505 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000506 }
507
Greg Clayton902b5be2011-10-26 04:32:38 +0000508 lldb::addr_t addr;
509 size_t total_byte_size = 0;
510 if (argc == 0)
511 {
512 // Use the last address and byte size and all options as they were
513 // if no options have been set
514 addr = m_next_addr;
515 total_byte_size = m_prev_byte_size;
516 if (!m_format_options.AnyOptionWasSet() &&
517 !m_memory_options.AnyOptionWasSet() &&
518 !m_outfile_options.AnyOptionWasSet() &&
519 !m_varobj_options.AnyOptionWasSet())
520 {
521 m_format_options = m_prev_format_options;
522 m_memory_options = m_prev_memory_options;
523 m_outfile_options = m_prev_outfile_options;
524 m_varobj_options = m_prev_varobj_options;
525 }
526 }
527
Greg Claytona42880a2011-10-25 06:44:01 +0000528 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
529 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000530 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000531
Chris Lattner24943d22010-06-08 16:52:24 +0000532 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000533 {
534 total_byte_size = item_count * item_byte_size;
535 if (total_byte_size == 0)
536 total_byte_size = 32;
537 }
Chris Lattner24943d22010-06-08 16:52:24 +0000538
Greg Clayton902b5be2011-10-26 04:32:38 +0000539 if (argc > 0)
540 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000541
542 if (addr == LLDB_INVALID_ADDRESS)
543 {
544 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
545 result.SetStatus(eReturnStatusFailed);
546 return false;
547 }
548
549 if (argc == 2)
550 {
551 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
552 if (end_addr == LLDB_INVALID_ADDRESS)
553 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000554 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000555 result.SetStatus(eReturnStatusFailed);
556 return false;
557 }
558 else if (end_addr <= addr)
559 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000560 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 +0000561 result.SetStatus(eReturnStatusFailed);
562 return false;
563 }
Greg Claytona42880a2011-10-25 06:44:01 +0000564 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000565 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000566 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 +0000567 result.SetStatus(eReturnStatusFailed);
568 return false;
569 }
570
571 total_byte_size = end_addr - addr;
572 item_count = total_byte_size / item_byte_size;
573 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000574
575 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000576 size_t bytes_read = 0;
577 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000578 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000579 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Jim Ingham8cc3f692011-07-09 00:55:34 +0000580 Address address(NULL, addr);
Greg Clayton567e7f32011-09-22 04:58:26 +0000581 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000582 if (bytes_read == 0)
583 {
584 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
585 result.AppendError(error.AsCString());
586 result.SetStatus(eReturnStatusFailed);
587 return false;
588 }
589
590 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000591 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
Greg Clayton902b5be2011-10-26 04:32:38 +0000592 else
593 {
594 m_next_addr = addr + bytes_read;
595 m_prev_byte_size = bytes_read;
596 m_prev_format_options = m_format_options;
597 m_prev_memory_options = m_memory_options;
598 m_prev_outfile_options = m_outfile_options;
599 m_prev_varobj_options = m_varobj_options;
600 }
Chris Lattner24943d22010-06-08 16:52:24 +0000601 }
602
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000603 StreamFile outfile_stream;
604 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000605 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
606 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000607 {
608 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000609 outfile_spec.GetPath (path, sizeof(path));
610
611 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
612 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
613 if (append)
614 open_options |= File::eOpenOptionAppend;
615
616 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000617 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000618 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000619 {
620 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
621 if (bytes_written > 0)
622 {
623 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
624 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000625 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000626 path);
627 return true;
628 }
629 else
630 {
631 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
632 result.SetStatus(eReturnStatusFailed);
633 return false;
634 }
635 }
636 else
637 {
638 // We are going to write ASCII to the file just point the
639 // output_stream to our outfile_stream...
640 output_stream = &outfile_stream;
641 }
642 }
643 else
644 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000645 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000646 result.SetStatus(eReturnStatusFailed);
647 return false;
648 }
649 }
650 else
651 {
652 output_stream = &result.GetOutputStream();
653 }
654
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000655
656 if (clang_ast_type.GetOpaqueQualType())
657 {
658 for (uint32_t i = 0; i<item_count; ++i)
659 {
660 addr_t item_addr = addr + (i * item_byte_size);
661 Address address (NULL, item_addr);
662 StreamString name_strm;
663 name_strm.Printf ("0x%llx", item_addr);
664 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
665 name_strm.GetString().c_str(),
666 address,
667 clang_ast_type));
668 if (valobj_sp)
669 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000670 if (format != eFormatDefault)
671 valobj_sp->SetFormat (format);
672
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000673 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000674
675 ValueObject::DumpValueObject (*output_stream,
676 valobj_sp.get(),
677 NULL,
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000678 m_varobj_options.ptr_depth,
679 0,
680 m_varobj_options.max_depth,
681 m_varobj_options.show_types,
682 m_varobj_options.show_location,
683 m_varobj_options.use_objc,
Jim Ingham10de7d12011-05-04 03:43:18 +0000684 m_varobj_options.use_dynamic,
Enrico Granata840eb262011-08-09 23:50:01 +0000685 m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000686 scope_already_checked,
Enrico Granata7f163b32011-07-16 01:22:04 +0000687 m_varobj_options.flat_output,
Enrico Granata018921d2011-08-12 02:00:06 +0000688 m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth,
689 m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000690 }
691 else
692 {
693 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
694 view_as_type_cstr,
695 name_strm.GetString().c_str());
696 result.SetStatus(eReturnStatusFailed);
697 return false;
698 }
699 }
700 return true;
701 }
702
703 result.SetStatus(eReturnStatusSuccessFinishResult);
704 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000705 target->GetArchitecture().GetByteOrder(),
706 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000707
708
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000709 assert (output_stream);
710 data.Dump (output_stream,
711 0,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000712 m_format_options.GetFormat(),
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000713 item_byte_size,
714 item_count,
715 num_per_line,
716 addr,
717 0,
718 0);
719 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000720 return true;
721 }
722
723protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000724 OptionGroupOptions m_option_group;
725 OptionGroupFormat m_format_options;
726 OptionGroupReadMemory m_memory_options;
727 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000728 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000729 lldb::addr_t m_next_addr;
730 lldb::addr_t m_prev_byte_size;
731 OptionGroupFormat m_prev_format_options;
732 OptionGroupReadMemory m_prev_memory_options;
733 OptionGroupOutputFile m_prev_outfile_options;
734 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000735};
736
Greg Claytona42880a2011-10-25 06:44:01 +0000737
738OptionDefinition
739g_memory_write_option_table[] =
740{
741{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
742{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
743};
744
745
Chris Lattner24943d22010-06-08 16:52:24 +0000746//----------------------------------------------------------------------
747// Write memory to the inferior process
748//----------------------------------------------------------------------
749class CommandObjectMemoryWrite : public CommandObject
750{
751public:
752
Greg Claytona42880a2011-10-25 06:44:01 +0000753 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000754 {
755 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000756 OptionGroupWriteMemory () :
757 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000758 {
Chris Lattner24943d22010-06-08 16:52:24 +0000759 }
760
761 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000762 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000763 {
764 }
765
Greg Claytona42880a2011-10-25 06:44:01 +0000766 virtual uint32_t
767 GetNumDefinitions ()
768 {
769 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
770 }
771
772 virtual const OptionDefinition*
773 GetDefinitions ()
774 {
775 return g_memory_write_option_table;
776 }
777
Chris Lattner24943d22010-06-08 16:52:24 +0000778 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000779 SetOptionValue (CommandInterpreter &interpreter,
780 uint32_t option_idx,
781 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000782 {
783 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000784 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
785
Chris Lattner24943d22010-06-08 16:52:24 +0000786 switch (short_option)
787 {
Greg Claytona42880a2011-10-25 06:44:01 +0000788 case 'i':
789 m_infile.SetFile (option_arg, true);
790 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000791 {
Greg Claytona42880a2011-10-25 06:44:01 +0000792 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000793 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000794 }
Greg Claytona42880a2011-10-25 06:44:01 +0000795 break;
796
797 case 'o':
798 {
799 bool success;
800 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
801 if (!success)
802 {
Greg Clayton9c236732011-10-26 00:56:27 +0000803 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000804 }
805 }
806 break;
807
808 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000809 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000810 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000811 }
812 return error;
813 }
Greg Claytona42880a2011-10-25 06:44:01 +0000814
815 virtual void
816 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000817 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000818 m_infile.Clear();
819 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000820 }
821
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000822 FileSpec m_infile;
823 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000824 };
825
Greg Clayton238c0a12010-09-18 01:14:36 +0000826 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
827 CommandObject (interpreter,
828 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000829 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000830 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
831 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000832 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000833 m_option_group (interpreter),
834 m_format_options (eFormatBytes, 1, UINT64_MAX),
835 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000836 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000837 CommandArgumentEntry arg1;
838 CommandArgumentEntry arg2;
839 CommandArgumentData addr_arg;
840 CommandArgumentData value_arg;
841
842 // Define the first (and only) variant of this arg.
843 addr_arg.arg_type = eArgTypeAddress;
844 addr_arg.arg_repetition = eArgRepeatPlain;
845
846 // There is only one variant this argument could be; put it into the argument entry.
847 arg1.push_back (addr_arg);
848
849 // Define the first (and only) variant of this arg.
850 value_arg.arg_type = eArgTypeValue;
851 value_arg.arg_repetition = eArgRepeatPlus;
852
853 // There is only one variant this argument could be; put it into the argument entry.
854 arg2.push_back (value_arg);
855
856 // Push the data for the first argument into the m_arguments vector.
857 m_arguments.push_back (arg1);
858 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000859
860 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
861 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
862 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
863 m_option_group.Finalize();
864
Chris Lattner24943d22010-06-08 16:52:24 +0000865 }
866
867 virtual
868 ~CommandObjectMemoryWrite ()
869 {
870 }
871
872 Options *
873 GetOptions ()
874 {
Greg Claytona42880a2011-10-25 06:44:01 +0000875 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000876 }
877
878 bool
879 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
880 {
881 if (total_byte_size > 8)
882 return false;
883
884 if (total_byte_size == 8)
885 return true;
886
887 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
888 return uval64 <= max;
889 }
890
891 bool
892 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
893 {
894 if (total_byte_size > 8)
895 return false;
896
897 if (total_byte_size == 8)
898 return true;
899
900 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
901 const int64_t min = ~(max);
902 return min <= sval64 && sval64 <= max;
903 }
904
905 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000906 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000907 CommandReturnObject &result)
908 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000909 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000910 if (process == NULL)
911 {
912 result.AppendError("need a process to read memory");
913 result.SetStatus(eReturnStatusFailed);
914 return false;
915 }
916
917 const size_t argc = command.GetArgumentCount();
918
Greg Claytona42880a2011-10-25 06:44:01 +0000919 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000920 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000921 if (argc < 1)
922 {
923 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
924 result.SetStatus(eReturnStatusFailed);
925 return false;
926 }
927 }
928 else if (argc < 2)
929 {
930 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 +0000931 result.SetStatus(eReturnStatusFailed);
932 return false;
933 }
934
Chris Lattner24943d22010-06-08 16:52:24 +0000935 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000936 process->GetTarget().GetArchitecture().GetAddressByteSize(),
937 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000938
Greg Claytona42880a2011-10-25 06:44:01 +0000939 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
940 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000941
Chris Lattner24943d22010-06-08 16:52:24 +0000942 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
943
944 if (addr == LLDB_INVALID_ADDRESS)
945 {
946 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
947 result.SetStatus(eReturnStatusFailed);
948 return false;
949 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000950
Greg Claytona42880a2011-10-25 06:44:01 +0000951 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000952 {
953 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000954 if (item_byte_size > 0)
955 length = item_byte_size;
956 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000957 if (data_sp)
958 {
959 length = data_sp->GetByteSize();
960 if (length > 0)
961 {
962 Error error;
963 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
964
965 if (bytes_written == length)
966 {
967 // All bytes written
968 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
969 result.SetStatus(eReturnStatusSuccessFinishResult);
970 }
971 else if (bytes_written > 0)
972 {
973 // Some byte written
974 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
975 result.SetStatus(eReturnStatusSuccessFinishResult);
976 }
977 else
978 {
979 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
980 result.SetStatus(eReturnStatusFailed);
981 }
982 }
983 }
984 else
985 {
986 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
987 result.SetStatus(eReturnStatusFailed);
988 }
989 return result.Succeeded();
990 }
Greg Claytona42880a2011-10-25 06:44:01 +0000991 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000992 {
Greg Claytona42880a2011-10-25 06:44:01 +0000993 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000994 item_byte_size = buffer.GetAddressByteSize();
995 else
996 item_byte_size = 1;
997 }
998
Chris Lattner24943d22010-06-08 16:52:24 +0000999 command.Shift(); // shift off the address argument
1000 uint64_t uval64;
1001 int64_t sval64;
1002 bool success = false;
1003 const uint32_t num_value_args = command.GetArgumentCount();
1004 uint32_t i;
1005 for (i=0; i<num_value_args; ++i)
1006 {
1007 const char *value_str = command.GetArgumentAtIndex(i);
1008
Greg Claytona42880a2011-10-25 06:44:01 +00001009 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001010 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001011 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001012 case eFormatFloat: // TODO: add support for floats soon
1013 case eFormatCharPrintable:
1014 case eFormatBytesWithASCII:
1015 case eFormatComplex:
1016 case eFormatEnum:
1017 case eFormatUnicode16:
1018 case eFormatUnicode32:
1019 case eFormatVectorOfChar:
1020 case eFormatVectorOfSInt8:
1021 case eFormatVectorOfUInt8:
1022 case eFormatVectorOfSInt16:
1023 case eFormatVectorOfUInt16:
1024 case eFormatVectorOfSInt32:
1025 case eFormatVectorOfUInt32:
1026 case eFormatVectorOfSInt64:
1027 case eFormatVectorOfUInt64:
1028 case eFormatVectorOfFloat32:
1029 case eFormatVectorOfFloat64:
1030 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001031 case eFormatOSType:
1032 case eFormatComplexInteger:
Chris Lattner24943d22010-06-08 16:52:24 +00001033 result.AppendError("unsupported format for writing memory");
1034 result.SetStatus(eReturnStatusFailed);
1035 return false;
1036
1037 case eFormatDefault:
1038 case eFormatBytes:
1039 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001040 case eFormatPointer:
1041
Chris Lattner24943d22010-06-08 16:52:24 +00001042 // Decode hex bytes
1043 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1044 if (!success)
1045 {
1046 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1047 result.SetStatus(eReturnStatusFailed);
1048 return false;
1049 }
1050 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1051 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001052 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 +00001053 result.SetStatus(eReturnStatusFailed);
1054 return false;
1055 }
1056 buffer.PutMaxHex64 (uval64, item_byte_size);
1057 break;
1058
1059 case eFormatBoolean:
1060 uval64 = Args::StringToBoolean(value_str, false, &success);
1061 if (!success)
1062 {
1063 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1064 result.SetStatus(eReturnStatusFailed);
1065 return false;
1066 }
1067 buffer.PutMaxHex64 (uval64, item_byte_size);
1068 break;
1069
1070 case eFormatBinary:
1071 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1072 if (!success)
1073 {
1074 result.AppendErrorWithFormat ("'%s' is not a valid binary 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 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 +00001081 result.SetStatus(eReturnStatusFailed);
1082 return false;
1083 }
1084 buffer.PutMaxHex64 (uval64, item_byte_size);
1085 break;
1086
Greg Clayton307fa072011-06-17 23:50:44 +00001087 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001088 case eFormatChar:
1089 case eFormatCString:
1090 if (value_str[0])
1091 {
1092 size_t len = strlen (value_str);
1093 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001094 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001095 ++len;
1096 Error error;
1097 if (process->WriteMemory (addr, value_str, len, error) == len)
1098 {
1099 addr += len;
1100 }
1101 else
1102 {
1103 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1104 result.SetStatus(eReturnStatusFailed);
1105 return false;
1106 }
1107 }
1108 break;
1109
1110 case eFormatDecimal:
1111 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1112 if (!success)
1113 {
1114 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1115 result.SetStatus(eReturnStatusFailed);
1116 return false;
1117 }
1118 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1119 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001120 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 +00001121 result.SetStatus(eReturnStatusFailed);
1122 return false;
1123 }
1124 buffer.PutMaxHex64 (sval64, item_byte_size);
1125 break;
1126
1127 case eFormatUnsigned:
1128 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1129 if (!success)
1130 {
1131 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1132 result.SetStatus(eReturnStatusFailed);
1133 return false;
1134 }
1135 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1136 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001137 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 +00001138 result.SetStatus(eReturnStatusFailed);
1139 return false;
1140 }
1141 buffer.PutMaxHex64 (uval64, item_byte_size);
1142 break;
1143
1144 case eFormatOctal:
1145 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1146 if (!success)
1147 {
1148 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1149 result.SetStatus(eReturnStatusFailed);
1150 return false;
1151 }
1152 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1153 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001154 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 +00001155 result.SetStatus(eReturnStatusFailed);
1156 return false;
1157 }
1158 buffer.PutMaxHex64 (uval64, item_byte_size);
1159 break;
1160 }
1161 }
1162
1163 if (!buffer.GetString().empty())
1164 {
1165 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001166 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001167 return true;
1168 else
1169 {
1170 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1171 result.SetStatus(eReturnStatusFailed);
1172 return false;
1173 }
1174 }
1175 return true;
1176 }
1177
1178protected:
Greg Claytona42880a2011-10-25 06:44:01 +00001179
1180 OptionGroupOptions m_option_group;
1181 OptionGroupFormat m_format_options;
1182 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001183};
1184
Chris Lattner24943d22010-06-08 16:52:24 +00001185
1186//-------------------------------------------------------------------------
1187// CommandObjectMemory
1188//-------------------------------------------------------------------------
1189
Greg Clayton63094e02010-06-23 01:19:29 +00001190CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001191 CommandObjectMultiword (interpreter,
1192 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001193 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001194 "memory <subcommand> [<subcommand-options>]")
1195{
Greg Clayton238c0a12010-09-18 01:14:36 +00001196 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1197 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001198}
1199
1200CommandObjectMemory::~CommandObjectMemory ()
1201{
1202}