blob: 7a16a60bc0e52ca9b90ab35fb135cdfcf0f0bf79 [file] [log] [blame]
Chris Lattner30fdc8d2010-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 Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000018#include "lldb/Core/Debugger.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000020#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton66111032010-06-23 01:19:29 +000021#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000023#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000025#include "lldb/Interpreter/OptionGroupFormat.h"
26#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000027#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Sean Callananb6d70eb2011-10-12 02:08:07 +000028#include "lldb/Symbol/ClangNamespaceDecl.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029#include "lldb/Target/Process.h"
Greg Clayton84c39662011-04-27 22:04:39 +000030#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031
32using namespace lldb;
33using namespace lldb_private;
34
Greg Clayton68ebae62011-04-28 20:55:26 +000035static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000036g_option_table[] =
37{
Greg Clayton84c39662011-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 Clayton68ebae62011-04-28 20:55:26 +000050 m_num_per_line (1,1),
Greg Clayton84c39662011-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 Clayton86edbf42011-10-26 00:56:27 +000087 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +000088 break;
Greg Clayton1deb7962011-10-25 06:44:01 +000089
Greg Clayton84c39662011-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 Clayton86edbf42011-10-26 00:56:27 +000099 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000100 break;
101 }
102 return error;
103 }
104
105 virtual void
106 OptionParsingStarting (CommandInterpreter &interpreter)
107 {
Greg Clayton84c39662011-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 Clayton68ebae62011-04-28 20:55:26 +0000113 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000114 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000115 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000116 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000117 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
118 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000119 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000120 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000121 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000122
Greg Clayton68ebae62011-04-28 20:55:26 +0000123 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000124 {
125 default:
126 break;
127
128 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000129 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000130 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000131 if (!num_per_line_option_set)
132 m_num_per_line = 1;
133 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000134 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000135 break;
136
137 case eFormatCString:
138 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000139
140 case eFormatInstruction:
141 if (count_option_set)
142 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue();
143 m_num_per_line = 1;
144 break;
145
146 case eFormatAddressInfo:
147 if (!byte_size_option_set)
148 byte_size_value = target->GetArchitecture().GetAddressByteSize();
149 m_num_per_line = 1;
150 if (!count_option_set)
151 format_options.GetCountValue() = 8;
152 break;
153
Greg Clayton84c39662011-04-27 22:04:39 +0000154 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000155 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000156 if (!num_per_line_option_set)
157 m_num_per_line = 4;
158 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000159 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000160 break;
161
162 case eFormatBinary:
163 case eFormatFloat:
164 case eFormatOctal:
165 case eFormatDecimal:
166 case eFormatEnum:
167 case eFormatUnicode16:
168 case eFormatUnicode32:
169 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000170 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000171 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000172 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000173 if (!num_per_line_option_set)
174 m_num_per_line = 1;
175 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000176 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000177 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000178
Greg Clayton84c39662011-04-27 22:04:39 +0000179 case eFormatBytes:
180 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000181 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000182 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000183 if (byte_size_value > 1)
Greg Clayton68ebae62011-04-28 20:55:26 +0000184 error.SetErrorString ("use --count option to specify an end address to display a number of bytes");
185 }
186 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000187 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000188 if (!num_per_line_option_set)
189 m_num_per_line = 16;
190 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000191 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000192 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000193 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000194 case eFormatChar:
195 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000196 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000197 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000198 if (!num_per_line_option_set)
199 m_num_per_line = 32;
200 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000201 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000202 break;
203 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000204 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000205 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000206 if (!num_per_line_option_set)
207 m_num_per_line = 1;
208 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000209 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000210 break;
211 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000212 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000213 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000214 if (!num_per_line_option_set)
215 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000216 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000217 {
218 case 1:
219 case 2:
220 m_num_per_line = 8;
221 break;
222 case 4:
223 m_num_per_line = 4;
224 break;
225 case 8:
226 m_num_per_line = 2;
227 break;
228 default:
229 m_num_per_line = 1;
230 break;
231 }
232 }
233 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000234 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000235 break;
236
237 case eFormatVectorOfChar:
238 case eFormatVectorOfSInt8:
239 case eFormatVectorOfUInt8:
240 case eFormatVectorOfSInt16:
241 case eFormatVectorOfUInt16:
242 case eFormatVectorOfSInt32:
243 case eFormatVectorOfUInt32:
244 case eFormatVectorOfSInt64:
245 case eFormatVectorOfUInt64:
246 case eFormatVectorOfFloat32:
247 case eFormatVectorOfFloat64:
248 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000249 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000250 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000251 if (!num_per_line_option_set)
252 m_num_per_line = 1;
253 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000254 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000255 break;
256 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000257 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000258 }
259
Greg Clayton82f4cf42011-10-26 04:32:38 +0000260 bool
261 AnyOptionWasSet () const
262 {
263 return m_num_per_line.OptionWasSet() ||
264 m_output_as_binary ||
265 m_view_as_type.OptionWasSet();
266 }
267
Greg Clayton84c39662011-04-27 22:04:39 +0000268 OptionValueUInt64 m_num_per_line;
269 bool m_output_as_binary;
270 OptionValueString m_view_as_type;
271};
272
273
274
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000275//----------------------------------------------------------------------
276// Read memory from the inferior process
277//----------------------------------------------------------------------
278class CommandObjectMemoryRead : public CommandObject
279{
280public:
281
Greg Claytona7015092010-09-18 01:14:36 +0000282 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
283 CommandObject (interpreter,
284 "memory read",
Caroline Ticee3d26312010-09-08 21:06:11 +0000285 "Read from the memory of the process being debugged.",
Caroline Tice405fe672010-10-04 22:28:36 +0000286 NULL,
Jim Inghamb8e8a5f2011-07-09 00:55:34 +0000287 eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000288 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000289 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000290 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000291 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000292 m_varobj_options(),
293 m_next_addr(LLDB_INVALID_ADDRESS),
294 m_prev_byte_size(0),
295 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
296 m_prev_memory_options (),
297 m_prev_outfile_options (),
298 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000299 {
Caroline Tice405fe672010-10-04 22:28:36 +0000300 CommandArgumentEntry arg1;
301 CommandArgumentEntry arg2;
302 CommandArgumentData start_addr_arg;
303 CommandArgumentData end_addr_arg;
304
305 // Define the first (and only) variant of this arg.
306 start_addr_arg.arg_type = eArgTypeStartAddress;
307 start_addr_arg.arg_repetition = eArgRepeatPlain;
308
309 // There is only one variant this argument could be; put it into the argument entry.
310 arg1.push_back (start_addr_arg);
311
312 // Define the first (and only) variant of this arg.
313 end_addr_arg.arg_type = eArgTypeEndAddress;
314 end_addr_arg.arg_repetition = eArgRepeatOptional;
315
316 // There is only one variant this argument could be; put it into the argument entry.
317 arg2.push_back (end_addr_arg);
318
319 // Push the data for the first argument into the m_arguments vector.
320 m_arguments.push_back (arg1);
321 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000322
Greg Clayton1deb7962011-10-25 06:44:01 +0000323 // Add the "--format" and "--count" options to group 1 and 3
324 m_option_group.Append (&m_format_options,
325 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
326 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000327 m_option_group.Append (&m_format_options,
328 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
329 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000330 // Add the "--size" option to group 1 and 2
331 m_option_group.Append (&m_format_options,
332 OptionGroupFormat::OPTION_GROUP_SIZE,
333 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000334 m_option_group.Append (&m_memory_options);
335 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton68ebae62011-04-28 20:55:26 +0000336 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000337 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000338 }
339
340 virtual
341 ~CommandObjectMemoryRead ()
342 {
343 }
344
345 Options *
346 GetOptions ()
347 {
Greg Clayton84c39662011-04-27 22:04:39 +0000348 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000349 }
350
Greg Clayton82f4cf42011-10-26 04:32:38 +0000351 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
352 {
353 return m_cmd_name.c_str();
354 }
355
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356 virtual bool
Greg Claytona7015092010-09-18 01:14:36 +0000357 Execute (Args& command,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000358 CommandReturnObject &result)
359 {
Greg Clayton84c39662011-04-27 22:04:39 +0000360 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Claytonc14ee322011-09-22 04:58:26 +0000361 Target *target = exe_ctx.GetTargetPtr();
362 if (target == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000363 {
Jim Inghamb8e8a5f2011-07-09 00:55:34 +0000364 result.AppendError("need at least a target to read memory");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000365 result.SetStatus(eReturnStatusFailed);
366 return false;
367 }
368 const size_t argc = command.GetArgumentCount();
369
Greg Clayton84c39662011-04-27 22:04:39 +0000370
Greg Clayton82f4cf42011-10-26 04:32:38 +0000371 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000372 {
373 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
374 result.SetStatus(eReturnStatusFailed);
375 return false;
376 }
377
Greg Clayton68ebae62011-04-28 20:55:26 +0000378 ClangASTType clang_ast_type;
379 Error error;
380
381 Format format = m_format_options.GetFormat();
Greg Clayton84c39662011-04-27 22:04:39 +0000382 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
383 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384 {
Greg Clayton84c39662011-04-27 22:04:39 +0000385 // We are viewing memory as a type
386 SymbolContext sc;
387 const bool append = true;
388 TypeList type_list;
389 uint32_t reference_count = 0;
390 uint32_t pointer_count = 0;
391 size_t idx;
392 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
393 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
394 std::string type_str(view_as_type_cstr);
395
396 // Remove all instances of g_keywords that are followed by spaces
397 for (size_t i = 0; i < g_num_keywords; ++i)
398 {
399 const char *keyword = g_keywords[i];
400 int keyword_len = ::strlen (keyword);
401 while ((idx = type_str.find (keyword)) != std::string::npos)
402 {
403 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
404 type_str.erase(idx, keyword_len+1);
405 }
406 }
407 bool done = type_str.empty();
408 //
409 idx = type_str.find_first_not_of (" \t");
410 if (idx > 0 && idx != std::string::npos)
411 type_str.erase (0, idx);
412 while (!done)
413 {
414 // Strip trailing spaces
415 if (type_str.empty())
416 done = true;
417 else
418 {
419 switch (type_str[type_str.size()-1])
420 {
421 case '*':
422 ++pointer_count;
423 // fall through...
424 case ' ':
425 case '\t':
426 type_str.erase(type_str.size()-1);
427 break;
428
429 case '&':
430 if (reference_count == 0)
431 {
432 reference_count = 1;
433 type_str.erase(type_str.size()-1);
434 }
435 else
436 {
437 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
438 result.SetStatus(eReturnStatusFailed);
439 return false;
440 }
441 break;
442
443 default:
444 done = true;
445 break;
446 }
447 }
448 }
449
450 ConstString lookup_type_name(type_str.c_str());
Greg Claytonc14ee322011-09-22 04:58:26 +0000451 StackFrame *frame = exe_ctx.GetFramePtr();
452 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000453 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000454 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000455 if (sc.module_sp)
456 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000457 sc.module_sp->FindTypes (sc,
458 lookup_type_name,
459 NULL,
Greg Clayton84c39662011-04-27 22:04:39 +0000460 append,
461 1,
462 type_list);
463 }
464 }
465 if (type_list.GetSize() == 0)
466 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000467 target->GetImages().FindTypes (sc,
468 lookup_type_name,
469 append,
470 1,
471 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000472 }
473
474 if (type_list.GetSize() == 0)
475 {
476 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
477 lookup_type_name.GetCString(),
478 view_as_type_cstr);
479 result.SetStatus(eReturnStatusFailed);
480 return false;
481 }
482
483 TypeSP type_sp (type_list.GetTypeAtIndex(0));
484 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
485
486 while (pointer_count > 0)
487 {
488 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
489 if (pointer_type)
490 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
491 else
492 {
493 result.AppendError ("unable make a pointer type\n");
494 result.SetStatus(eReturnStatusFailed);
495 return false;
496 }
497 --pointer_count;
498 }
499
Greg Clayton1deb7962011-10-25 06:44:01 +0000500 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000501
Greg Clayton1deb7962011-10-25 06:44:01 +0000502 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000503 {
504 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
505 view_as_type_cstr);
506 result.SetStatus(eReturnStatusFailed);
507 return false;
508 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000509
Greg Clayton1deb7962011-10-25 06:44:01 +0000510 if (!m_format_options.GetCountValue().OptionWasSet())
511 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000512 }
513 else
514 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000515 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000516 }
517
518 // Look for invalid combinations of settings
519 if (error.Fail())
520 {
521 result.AppendErrorWithFormat("%s", error.AsCString());
522 result.SetStatus(eReturnStatusFailed);
523 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000524 }
525
Greg Clayton82f4cf42011-10-26 04:32:38 +0000526 lldb::addr_t addr;
527 size_t total_byte_size = 0;
528 if (argc == 0)
529 {
530 // Use the last address and byte size and all options as they were
531 // if no options have been set
532 addr = m_next_addr;
533 total_byte_size = m_prev_byte_size;
534 if (!m_format_options.AnyOptionWasSet() &&
535 !m_memory_options.AnyOptionWasSet() &&
536 !m_outfile_options.AnyOptionWasSet() &&
537 !m_varobj_options.AnyOptionWasSet())
538 {
539 m_format_options = m_prev_format_options;
540 m_memory_options = m_prev_memory_options;
541 m_outfile_options = m_prev_outfile_options;
542 m_varobj_options = m_prev_varobj_options;
543 }
544 }
545
Greg Clayton1deb7962011-10-25 06:44:01 +0000546 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
547 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000548 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000549
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000550 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000551 {
552 total_byte_size = item_count * item_byte_size;
553 if (total_byte_size == 0)
554 total_byte_size = 32;
555 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000556
Greg Clayton82f4cf42011-10-26 04:32:38 +0000557 if (argc > 0)
558 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000559
560 if (addr == LLDB_INVALID_ADDRESS)
561 {
562 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
563 result.SetStatus(eReturnStatusFailed);
564 return false;
565 }
566
567 if (argc == 2)
568 {
569 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
570 if (end_addr == LLDB_INVALID_ADDRESS)
571 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000572 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000573 result.SetStatus(eReturnStatusFailed);
574 return false;
575 }
576 else if (end_addr <= addr)
577 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000578 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000579 result.SetStatus(eReturnStatusFailed);
580 return false;
581 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000582 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000583 {
Jason Molendafd54b362011-09-20 21:44:10 +0000584 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000585 result.SetStatus(eReturnStatusFailed);
586 return false;
587 }
588
589 total_byte_size = end_addr - addr;
590 item_count = total_byte_size / item_byte_size;
591 }
Greg Clayton84c39662011-04-27 22:04:39 +0000592
593 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000594 size_t bytes_read = 0;
595 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000596 {
Greg Clayton84c39662011-04-27 22:04:39 +0000597 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Jim Inghamb8e8a5f2011-07-09 00:55:34 +0000598 Address address(NULL, addr);
Greg Claytonc14ee322011-09-22 04:58:26 +0000599 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000600 if (bytes_read == 0)
601 {
602 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
603 result.AppendError(error.AsCString());
604 result.SetStatus(eReturnStatusFailed);
605 return false;
606 }
607
608 if (bytes_read < total_byte_size)
Jason Molendafd54b362011-09-20 21:44:10 +0000609 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
Greg Clayton82f4cf42011-10-26 04:32:38 +0000610 else
611 {
612 m_next_addr = addr + bytes_read;
613 m_prev_byte_size = bytes_read;
614 m_prev_format_options = m_format_options;
615 m_prev_memory_options = m_memory_options;
616 m_prev_outfile_options = m_outfile_options;
617 m_prev_varobj_options = m_varobj_options;
618 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000619 }
620
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000621 StreamFile outfile_stream;
622 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000623 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
624 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000625 {
626 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000627 outfile_spec.GetPath (path, sizeof(path));
628
629 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
630 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
631 if (append)
632 open_options |= File::eOpenOptionAppend;
633
634 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000635 {
Greg Clayton84c39662011-04-27 22:04:39 +0000636 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000637 {
638 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
639 if (bytes_written > 0)
640 {
641 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
642 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000643 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000644 path);
645 return true;
646 }
647 else
648 {
649 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
650 result.SetStatus(eReturnStatusFailed);
651 return false;
652 }
653 }
654 else
655 {
656 // We are going to write ASCII to the file just point the
657 // output_stream to our outfile_stream...
658 output_stream = &outfile_stream;
659 }
660 }
661 else
662 {
Greg Clayton84c39662011-04-27 22:04:39 +0000663 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000664 result.SetStatus(eReturnStatusFailed);
665 return false;
666 }
667 }
668 else
669 {
670 output_stream = &result.GetOutputStream();
671 }
672
Greg Clayton84c39662011-04-27 22:04:39 +0000673
Greg Clayton5009f9d2011-10-27 17:55:14 +0000674 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000675 if (clang_ast_type.GetOpaqueQualType())
676 {
677 for (uint32_t i = 0; i<item_count; ++i)
678 {
679 addr_t item_addr = addr + (i * item_byte_size);
680 Address address (NULL, item_addr);
681 StreamString name_strm;
682 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000683 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000684 name_strm.GetString().c_str(),
685 address,
686 clang_ast_type));
687 if (valobj_sp)
688 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000689 if (format != eFormatDefault)
690 valobj_sp->SetFormat (format);
691
Greg Clayton68ebae62011-04-28 20:55:26 +0000692 bool scope_already_checked = true;
Greg Clayton84c39662011-04-27 22:04:39 +0000693
694 ValueObject::DumpValueObject (*output_stream,
695 valobj_sp.get(),
696 NULL,
Greg Clayton68ebae62011-04-28 20:55:26 +0000697 m_varobj_options.ptr_depth,
698 0,
699 m_varobj_options.max_depth,
700 m_varobj_options.show_types,
701 m_varobj_options.show_location,
702 m_varobj_options.use_objc,
Jim Ingham2837b762011-05-04 03:43:18 +0000703 m_varobj_options.use_dynamic,
Enrico Granatace68b022011-08-09 23:50:01 +0000704 m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
Greg Clayton84c39662011-04-27 22:04:39 +0000705 scope_already_checked,
Enrico Granata0c5ef692011-07-16 01:22:04 +0000706 m_varobj_options.flat_output,
Enrico Granata22c55d12011-08-12 02:00:06 +0000707 m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth,
708 m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap);
Greg Clayton84c39662011-04-27 22:04:39 +0000709 }
710 else
711 {
712 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
713 view_as_type_cstr,
714 name_strm.GetString().c_str());
715 result.SetStatus(eReturnStatusFailed);
716 return false;
717 }
718 }
719 return true;
720 }
721
722 result.SetStatus(eReturnStatusSuccessFinishResult);
723 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000724 target->GetArchitecture().GetByteOrder(),
725 target->GetArchitecture().GetAddressByteSize());
Greg Clayton84c39662011-04-27 22:04:39 +0000726
727
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000728 assert (output_stream);
729 data.Dump (output_stream,
730 0,
Greg Clayton84c39662011-04-27 22:04:39 +0000731 m_format_options.GetFormat(),
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000732 item_byte_size,
733 item_count,
734 num_per_line,
735 addr,
736 0,
Greg Clayton5009f9d2011-10-27 17:55:14 +0000737 0,
738 exe_scope);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000739 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000740 return true;
741 }
742
743protected:
Greg Clayton84c39662011-04-27 22:04:39 +0000744 OptionGroupOptions m_option_group;
745 OptionGroupFormat m_format_options;
746 OptionGroupReadMemory m_memory_options;
747 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000748 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000749 lldb::addr_t m_next_addr;
750 lldb::addr_t m_prev_byte_size;
751 OptionGroupFormat m_prev_format_options;
752 OptionGroupReadMemory m_prev_memory_options;
753 OptionGroupOutputFile m_prev_outfile_options;
754 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000755};
756
Greg Clayton1deb7962011-10-25 06:44:01 +0000757
758OptionDefinition
759g_memory_write_option_table[] =
760{
761{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
762{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
763};
764
765
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000766//----------------------------------------------------------------------
767// Write memory to the inferior process
768//----------------------------------------------------------------------
769class CommandObjectMemoryWrite : public CommandObject
770{
771public:
772
Greg Clayton1deb7962011-10-25 06:44:01 +0000773 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000774 {
775 public:
Greg Clayton1deb7962011-10-25 06:44:01 +0000776 OptionGroupWriteMemory () :
777 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000778 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000779 }
780
781 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +0000782 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000783 {
784 }
785
Greg Clayton1deb7962011-10-25 06:44:01 +0000786 virtual uint32_t
787 GetNumDefinitions ()
788 {
789 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
790 }
791
792 virtual const OptionDefinition*
793 GetDefinitions ()
794 {
795 return g_memory_write_option_table;
796 }
797
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000798 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000799 SetOptionValue (CommandInterpreter &interpreter,
800 uint32_t option_idx,
801 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000802 {
803 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000804 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
805
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000806 switch (short_option)
807 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000808 case 'i':
809 m_infile.SetFile (option_arg, true);
810 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000811 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000812 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +0000813 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000814 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000815 break;
816
817 case 'o':
818 {
819 bool success;
820 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
821 if (!success)
822 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000823 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +0000824 }
825 }
826 break;
827
828 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000829 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +0000830 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000831 }
832 return error;
833 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000834
835 virtual void
836 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000837 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000838 m_infile.Clear();
839 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000840 }
841
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000842 FileSpec m_infile;
843 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000844 };
845
Greg Claytona7015092010-09-18 01:14:36 +0000846 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
847 CommandObject (interpreter,
848 "memory write",
Caroline Ticee3d26312010-09-08 21:06:11 +0000849 "Write to the memory of the process being debugged.",
Caroline Tice405fe672010-10-04 22:28:36 +0000850 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
851 NULL,
Greg Claytoneb0103f2011-04-07 22:46:35 +0000852 eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +0000853 m_option_group (interpreter),
854 m_format_options (eFormatBytes, 1, UINT64_MAX),
855 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000856 {
Caroline Tice405fe672010-10-04 22:28:36 +0000857 CommandArgumentEntry arg1;
858 CommandArgumentEntry arg2;
859 CommandArgumentData addr_arg;
860 CommandArgumentData value_arg;
861
862 // Define the first (and only) variant of this arg.
863 addr_arg.arg_type = eArgTypeAddress;
864 addr_arg.arg_repetition = eArgRepeatPlain;
865
866 // There is only one variant this argument could be; put it into the argument entry.
867 arg1.push_back (addr_arg);
868
869 // Define the first (and only) variant of this arg.
870 value_arg.arg_type = eArgTypeValue;
871 value_arg.arg_repetition = eArgRepeatPlus;
872
873 // There is only one variant this argument could be; put it into the argument entry.
874 arg2.push_back (value_arg);
875
876 // Push the data for the first argument into the m_arguments vector.
877 m_arguments.push_back (arg1);
878 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +0000879
880 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
881 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
882 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
883 m_option_group.Finalize();
884
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000885 }
886
887 virtual
888 ~CommandObjectMemoryWrite ()
889 {
890 }
891
892 Options *
893 GetOptions ()
894 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000895 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000896 }
897
898 bool
899 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
900 {
901 if (total_byte_size > 8)
902 return false;
903
904 if (total_byte_size == 8)
905 return true;
906
907 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
908 return uval64 <= max;
909 }
910
911 bool
912 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
913 {
914 if (total_byte_size > 8)
915 return false;
916
917 if (total_byte_size == 8)
918 return true;
919
920 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
921 const int64_t min = ~(max);
922 return min <= sval64 && sval64 <= max;
923 }
924
925 virtual bool
Greg Claytona7015092010-09-18 01:14:36 +0000926 Execute (Args& command,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000927 CommandReturnObject &result)
928 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000929 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000930 if (process == NULL)
931 {
932 result.AppendError("need a process to read memory");
933 result.SetStatus(eReturnStatusFailed);
934 return false;
935 }
936
937 const size_t argc = command.GetArgumentCount();
938
Greg Clayton1deb7962011-10-25 06:44:01 +0000939 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000940 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000941 if (argc < 1)
942 {
943 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
944 result.SetStatus(eReturnStatusFailed);
945 return false;
946 }
947 }
948 else if (argc < 2)
949 {
950 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000951 result.SetStatus(eReturnStatusFailed);
952 return false;
953 }
954
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000955 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +0000956 process->GetTarget().GetArchitecture().GetAddressByteSize(),
957 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000958
Greg Clayton1deb7962011-10-25 06:44:01 +0000959 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
960 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +0000961
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000962 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
963
964 if (addr == LLDB_INVALID_ADDRESS)
965 {
966 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
967 result.SetStatus(eReturnStatusFailed);
968 return false;
969 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000970
Greg Clayton1deb7962011-10-25 06:44:01 +0000971 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000972 {
973 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +0000974 if (item_byte_size > 0)
975 length = item_byte_size;
976 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000977 if (data_sp)
978 {
979 length = data_sp->GetByteSize();
980 if (length > 0)
981 {
982 Error error;
983 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
984
985 if (bytes_written == length)
986 {
987 // All bytes written
988 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
989 result.SetStatus(eReturnStatusSuccessFinishResult);
990 }
991 else if (bytes_written > 0)
992 {
993 // Some byte written
994 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
995 result.SetStatus(eReturnStatusSuccessFinishResult);
996 }
997 else
998 {
999 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1000 result.SetStatus(eReturnStatusFailed);
1001 }
1002 }
1003 }
1004 else
1005 {
1006 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1007 result.SetStatus(eReturnStatusFailed);
1008 }
1009 return result.Succeeded();
1010 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001011 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001012 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001013 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001014 item_byte_size = buffer.GetAddressByteSize();
1015 else
1016 item_byte_size = 1;
1017 }
1018
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001019 command.Shift(); // shift off the address argument
1020 uint64_t uval64;
1021 int64_t sval64;
1022 bool success = false;
1023 const uint32_t num_value_args = command.GetArgumentCount();
1024 uint32_t i;
1025 for (i=0; i<num_value_args; ++i)
1026 {
1027 const char *value_str = command.GetArgumentAtIndex(i);
1028
Greg Clayton1deb7962011-10-25 06:44:01 +00001029 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001030 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001031 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001032 case eFormatFloat: // TODO: add support for floats soon
1033 case eFormatCharPrintable:
1034 case eFormatBytesWithASCII:
1035 case eFormatComplex:
1036 case eFormatEnum:
1037 case eFormatUnicode16:
1038 case eFormatUnicode32:
1039 case eFormatVectorOfChar:
1040 case eFormatVectorOfSInt8:
1041 case eFormatVectorOfUInt8:
1042 case eFormatVectorOfSInt16:
1043 case eFormatVectorOfUInt16:
1044 case eFormatVectorOfSInt32:
1045 case eFormatVectorOfUInt32:
1046 case eFormatVectorOfSInt64:
1047 case eFormatVectorOfUInt64:
1048 case eFormatVectorOfFloat32:
1049 case eFormatVectorOfFloat64:
1050 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001051 case eFormatOSType:
1052 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001053 case eFormatAddressInfo:
1054 case eFormatHexFloat:
1055 case eFormatInstruction:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001056 result.AppendError("unsupported format for writing memory");
1057 result.SetStatus(eReturnStatusFailed);
1058 return false;
1059
1060 case eFormatDefault:
1061 case eFormatBytes:
1062 case eFormatHex:
Greg Claytonc982c762010-07-09 20:39:50 +00001063 case eFormatPointer:
1064
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001065 // Decode hex bytes
1066 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1067 if (!success)
1068 {
1069 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1070 result.SetStatus(eReturnStatusFailed);
1071 return false;
1072 }
1073 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1074 {
Jason Molendafd54b362011-09-20 21:44:10 +00001075 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001076 result.SetStatus(eReturnStatusFailed);
1077 return false;
1078 }
1079 buffer.PutMaxHex64 (uval64, item_byte_size);
1080 break;
1081
1082 case eFormatBoolean:
1083 uval64 = Args::StringToBoolean(value_str, false, &success);
1084 if (!success)
1085 {
1086 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1087 result.SetStatus(eReturnStatusFailed);
1088 return false;
1089 }
1090 buffer.PutMaxHex64 (uval64, item_byte_size);
1091 break;
1092
1093 case eFormatBinary:
1094 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1095 if (!success)
1096 {
1097 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1098 result.SetStatus(eReturnStatusFailed);
1099 return false;
1100 }
1101 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1102 {
Jason Molendafd54b362011-09-20 21:44:10 +00001103 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001104 result.SetStatus(eReturnStatusFailed);
1105 return false;
1106 }
1107 buffer.PutMaxHex64 (uval64, item_byte_size);
1108 break;
1109
Greg Clayton4e4294b2011-06-17 23:50:44 +00001110 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001111 case eFormatChar:
1112 case eFormatCString:
1113 if (value_str[0])
1114 {
1115 size_t len = strlen (value_str);
1116 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001117 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001118 ++len;
1119 Error error;
1120 if (process->WriteMemory (addr, value_str, len, error) == len)
1121 {
1122 addr += len;
1123 }
1124 else
1125 {
1126 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1127 result.SetStatus(eReturnStatusFailed);
1128 return false;
1129 }
1130 }
1131 break;
1132
1133 case eFormatDecimal:
1134 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1135 if (!success)
1136 {
1137 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1138 result.SetStatus(eReturnStatusFailed);
1139 return false;
1140 }
1141 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1142 {
Jason Molendafd54b362011-09-20 21:44:10 +00001143 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001144 result.SetStatus(eReturnStatusFailed);
1145 return false;
1146 }
1147 buffer.PutMaxHex64 (sval64, item_byte_size);
1148 break;
1149
1150 case eFormatUnsigned:
1151 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1152 if (!success)
1153 {
1154 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1155 result.SetStatus(eReturnStatusFailed);
1156 return false;
1157 }
1158 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1159 {
Jason Molendafd54b362011-09-20 21:44:10 +00001160 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001161 result.SetStatus(eReturnStatusFailed);
1162 return false;
1163 }
1164 buffer.PutMaxHex64 (uval64, item_byte_size);
1165 break;
1166
1167 case eFormatOctal:
1168 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1169 if (!success)
1170 {
1171 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1172 result.SetStatus(eReturnStatusFailed);
1173 return false;
1174 }
1175 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1176 {
Jason Molendafd54b362011-09-20 21:44:10 +00001177 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001178 result.SetStatus(eReturnStatusFailed);
1179 return false;
1180 }
1181 buffer.PutMaxHex64 (uval64, item_byte_size);
1182 break;
1183 }
1184 }
1185
1186 if (!buffer.GetString().empty())
1187 {
1188 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001189 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001190 return true;
1191 else
1192 {
1193 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1194 result.SetStatus(eReturnStatusFailed);
1195 return false;
1196 }
1197 }
1198 return true;
1199 }
1200
1201protected:
Greg Clayton1deb7962011-10-25 06:44:01 +00001202
1203 OptionGroupOptions m_option_group;
1204 OptionGroupFormat m_format_options;
1205 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001206};
1207
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001208
1209//-------------------------------------------------------------------------
1210// CommandObjectMemory
1211//-------------------------------------------------------------------------
1212
Greg Clayton66111032010-06-23 01:19:29 +00001213CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001214 CommandObjectMultiword (interpreter,
1215 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001216 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001217 "memory <subcommand> [<subcommand-options>]")
1218{
Greg Claytona7015092010-09-18 01:14:36 +00001219 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1220 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001221}
1222
1223CommandObjectMemory::~CommandObjectMemory ()
1224{
1225}