blob: 558f84091483c97316962262850001c020e7b43f [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)
Johnny Chenda324de2012-03-06 01:17:59 +0000184 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n"
185 "\tconsider using a different display format or don't specify the byte size",
186 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000187 }
188 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000189 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000190 if (!num_per_line_option_set)
191 m_num_per_line = 16;
192 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000193 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000194 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000195 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000196 case eFormatChar:
197 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000198 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000199 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000200 if (!num_per_line_option_set)
201 m_num_per_line = 32;
202 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000203 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000204 break;
205 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000206 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000207 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000208 if (!num_per_line_option_set)
209 m_num_per_line = 1;
210 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000211 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000212 break;
213 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000214 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000215 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000216 if (!num_per_line_option_set)
217 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000218 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000219 {
220 case 1:
221 case 2:
222 m_num_per_line = 8;
223 break;
224 case 4:
225 m_num_per_line = 4;
226 break;
227 case 8:
228 m_num_per_line = 2;
229 break;
230 default:
231 m_num_per_line = 1;
232 break;
233 }
234 }
235 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000236 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000237 break;
238
239 case eFormatVectorOfChar:
240 case eFormatVectorOfSInt8:
241 case eFormatVectorOfUInt8:
242 case eFormatVectorOfSInt16:
243 case eFormatVectorOfUInt16:
244 case eFormatVectorOfSInt32:
245 case eFormatVectorOfUInt32:
246 case eFormatVectorOfSInt64:
247 case eFormatVectorOfUInt64:
248 case eFormatVectorOfFloat32:
249 case eFormatVectorOfFloat64:
250 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000251 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000252 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000253 if (!num_per_line_option_set)
254 m_num_per_line = 1;
255 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000256 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000257 break;
258 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000259 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000260 }
261
Greg Clayton82f4cf42011-10-26 04:32:38 +0000262 bool
263 AnyOptionWasSet () const
264 {
265 return m_num_per_line.OptionWasSet() ||
266 m_output_as_binary ||
267 m_view_as_type.OptionWasSet();
268 }
269
Greg Clayton84c39662011-04-27 22:04:39 +0000270 OptionValueUInt64 m_num_per_line;
271 bool m_output_as_binary;
272 OptionValueString m_view_as_type;
273};
274
275
276
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000277//----------------------------------------------------------------------
278// Read memory from the inferior process
279//----------------------------------------------------------------------
280class CommandObjectMemoryRead : public CommandObject
281{
282public:
283
Greg Claytona7015092010-09-18 01:14:36 +0000284 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
285 CommandObject (interpreter,
286 "memory read",
Caroline Ticee3d26312010-09-08 21:06:11 +0000287 "Read from the memory of the process being debugged.",
Caroline Tice405fe672010-10-04 22:28:36 +0000288 NULL,
Jim Inghamb8e8a5f2011-07-09 00:55:34 +0000289 eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000290 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000291 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000292 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000293 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000294 m_varobj_options(),
295 m_next_addr(LLDB_INVALID_ADDRESS),
296 m_prev_byte_size(0),
297 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
298 m_prev_memory_options (),
299 m_prev_outfile_options (),
300 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000301 {
Caroline Tice405fe672010-10-04 22:28:36 +0000302 CommandArgumentEntry arg1;
303 CommandArgumentEntry arg2;
304 CommandArgumentData start_addr_arg;
305 CommandArgumentData end_addr_arg;
306
307 // Define the first (and only) variant of this arg.
308 start_addr_arg.arg_type = eArgTypeStartAddress;
309 start_addr_arg.arg_repetition = eArgRepeatPlain;
310
311 // There is only one variant this argument could be; put it into the argument entry.
312 arg1.push_back (start_addr_arg);
313
314 // Define the first (and only) variant of this arg.
315 end_addr_arg.arg_type = eArgTypeEndAddress;
316 end_addr_arg.arg_repetition = eArgRepeatOptional;
317
318 // There is only one variant this argument could be; put it into the argument entry.
319 arg2.push_back (end_addr_arg);
320
321 // Push the data for the first argument into the m_arguments vector.
322 m_arguments.push_back (arg1);
323 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000324
Greg Clayton1deb7962011-10-25 06:44:01 +0000325 // Add the "--format" and "--count" options to group 1 and 3
326 m_option_group.Append (&m_format_options,
327 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000328 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000329 m_option_group.Append (&m_format_options,
330 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000331 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000332 // Add the "--size" option to group 1 and 2
333 m_option_group.Append (&m_format_options,
334 OptionGroupFormat::OPTION_GROUP_SIZE,
335 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000336 m_option_group.Append (&m_memory_options);
337 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 +0000338 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000339 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000340 }
341
342 virtual
343 ~CommandObjectMemoryRead ()
344 {
345 }
346
347 Options *
348 GetOptions ()
349 {
Greg Clayton84c39662011-04-27 22:04:39 +0000350 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000351 }
352
Greg Clayton82f4cf42011-10-26 04:32:38 +0000353 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
354 {
355 return m_cmd_name.c_str();
356 }
357
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000358 virtual bool
Greg Claytona7015092010-09-18 01:14:36 +0000359 Execute (Args& command,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000360 CommandReturnObject &result)
361 {
Greg Clayton84c39662011-04-27 22:04:39 +0000362 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Claytonc14ee322011-09-22 04:58:26 +0000363 Target *target = exe_ctx.GetTargetPtr();
364 if (target == NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000365 {
Jim Inghamb8e8a5f2011-07-09 00:55:34 +0000366 result.AppendError("need at least a target to read memory");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000367 result.SetStatus(eReturnStatusFailed);
368 return false;
369 }
370 const size_t argc = command.GetArgumentCount();
371
Greg Clayton84c39662011-04-27 22:04:39 +0000372
Greg Clayton82f4cf42011-10-26 04:32:38 +0000373 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000374 {
375 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
376 result.SetStatus(eReturnStatusFailed);
377 return false;
378 }
379
Greg Clayton68ebae62011-04-28 20:55:26 +0000380 ClangASTType clang_ast_type;
381 Error error;
382
383 Format format = m_format_options.GetFormat();
Greg Clayton84c39662011-04-27 22:04:39 +0000384 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
385 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000386 {
Greg Clayton84c39662011-04-27 22:04:39 +0000387 // We are viewing memory as a type
388 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000389 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000390 TypeList type_list;
391 uint32_t reference_count = 0;
392 uint32_t pointer_count = 0;
393 size_t idx;
394 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
395 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
396 std::string type_str(view_as_type_cstr);
397
398 // Remove all instances of g_keywords that are followed by spaces
399 for (size_t i = 0; i < g_num_keywords; ++i)
400 {
401 const char *keyword = g_keywords[i];
402 int keyword_len = ::strlen (keyword);
403 while ((idx = type_str.find (keyword)) != std::string::npos)
404 {
405 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
406 type_str.erase(idx, keyword_len+1);
407 }
408 }
409 bool done = type_str.empty();
410 //
411 idx = type_str.find_first_not_of (" \t");
412 if (idx > 0 && idx != std::string::npos)
413 type_str.erase (0, idx);
414 while (!done)
415 {
416 // Strip trailing spaces
417 if (type_str.empty())
418 done = true;
419 else
420 {
421 switch (type_str[type_str.size()-1])
422 {
423 case '*':
424 ++pointer_count;
425 // fall through...
426 case ' ':
427 case '\t':
428 type_str.erase(type_str.size()-1);
429 break;
430
431 case '&':
432 if (reference_count == 0)
433 {
434 reference_count = 1;
435 type_str.erase(type_str.size()-1);
436 }
437 else
438 {
439 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
440 result.SetStatus(eReturnStatusFailed);
441 return false;
442 }
443 break;
444
445 default:
446 done = true;
447 break;
448 }
449 }
450 }
451
452 ConstString lookup_type_name(type_str.c_str());
Greg Claytonc14ee322011-09-22 04:58:26 +0000453 StackFrame *frame = exe_ctx.GetFramePtr();
454 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000455 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000456 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000457 if (sc.module_sp)
458 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000459 sc.module_sp->FindTypes (sc,
460 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000461 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000462 1,
463 type_list);
464 }
465 }
466 if (type_list.GetSize() == 0)
467 {
Greg Clayton29399a22012-04-06 17:41:13 +0000468 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000469 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000470 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000471 1,
472 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000473 }
474
475 if (type_list.GetSize() == 0)
476 {
477 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
478 lookup_type_name.GetCString(),
479 view_as_type_cstr);
480 result.SetStatus(eReturnStatusFailed);
481 return false;
482 }
483
484 TypeSP type_sp (type_list.GetTypeAtIndex(0));
485 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
486
487 while (pointer_count > 0)
488 {
489 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
490 if (pointer_type)
491 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
492 else
493 {
494 result.AppendError ("unable make a pointer type\n");
495 result.SetStatus(eReturnStatusFailed);
496 return false;
497 }
498 --pointer_count;
499 }
500
Greg Clayton1deb7962011-10-25 06:44:01 +0000501 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000502
Greg Clayton1deb7962011-10-25 06:44:01 +0000503 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000504 {
505 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
506 view_as_type_cstr);
507 result.SetStatus(eReturnStatusFailed);
508 return false;
509 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000510
Greg Clayton1deb7962011-10-25 06:44:01 +0000511 if (!m_format_options.GetCountValue().OptionWasSet())
512 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000513 }
514 else
515 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000516 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000517 }
518
519 // Look for invalid combinations of settings
520 if (error.Fail())
521 {
522 result.AppendErrorWithFormat("%s", error.AsCString());
523 result.SetStatus(eReturnStatusFailed);
524 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000525 }
526
Greg Clayton82f4cf42011-10-26 04:32:38 +0000527 lldb::addr_t addr;
528 size_t total_byte_size = 0;
529 if (argc == 0)
530 {
531 // Use the last address and byte size and all options as they were
532 // if no options have been set
533 addr = m_next_addr;
534 total_byte_size = m_prev_byte_size;
535 if (!m_format_options.AnyOptionWasSet() &&
536 !m_memory_options.AnyOptionWasSet() &&
537 !m_outfile_options.AnyOptionWasSet() &&
538 !m_varobj_options.AnyOptionWasSet())
539 {
540 m_format_options = m_prev_format_options;
541 m_memory_options = m_prev_memory_options;
542 m_outfile_options = m_prev_outfile_options;
543 m_varobj_options = m_prev_varobj_options;
544 }
545 }
546
Greg Clayton1deb7962011-10-25 06:44:01 +0000547 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
548 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000549 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000550
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000552 {
553 total_byte_size = item_count * item_byte_size;
554 if (total_byte_size == 0)
555 total_byte_size = 32;
556 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000557
Greg Clayton82f4cf42011-10-26 04:32:38 +0000558 if (argc > 0)
559 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000560
561 if (addr == LLDB_INVALID_ADDRESS)
562 {
563 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
564 result.SetStatus(eReturnStatusFailed);
565 return false;
566 }
567
568 if (argc == 2)
569 {
570 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
571 if (end_addr == LLDB_INVALID_ADDRESS)
572 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000573 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000574 result.SetStatus(eReturnStatusFailed);
575 return false;
576 }
577 else if (end_addr <= addr)
578 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000579 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 +0000580 result.SetStatus(eReturnStatusFailed);
581 return false;
582 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000583 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000584 {
Jason Molendafd54b362011-09-20 21:44:10 +0000585 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 +0000586 result.SetStatus(eReturnStatusFailed);
587 return false;
588 }
589
590 total_byte_size = end_addr - addr;
591 item_count = total_byte_size / item_byte_size;
592 }
Greg Clayton84c39662011-04-27 22:04:39 +0000593
594 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000595 size_t bytes_read = 0;
596 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000597 {
Greg Clayton84c39662011-04-27 22:04:39 +0000598 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Claytone72dfb32012-02-24 01:59:29 +0000599 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000600 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000601 if (bytes_read == 0)
602 {
603 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
604 result.AppendError(error.AsCString());
605 result.SetStatus(eReturnStatusFailed);
606 return false;
607 }
608
609 if (bytes_read < total_byte_size)
Jason Molendafd54b362011-09-20 21:44:10 +0000610 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 +0000611 else
612 {
613 m_next_addr = addr + bytes_read;
614 m_prev_byte_size = bytes_read;
615 m_prev_format_options = m_format_options;
616 m_prev_memory_options = m_memory_options;
617 m_prev_outfile_options = m_outfile_options;
618 m_prev_varobj_options = m_varobj_options;
619 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000620 }
621
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000622 StreamFile outfile_stream;
623 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000624 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
625 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000626 {
627 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000628 outfile_spec.GetPath (path, sizeof(path));
629
630 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
631 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
632 if (append)
633 open_options |= File::eOpenOptionAppend;
634
635 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000636 {
Greg Clayton84c39662011-04-27 22:04:39 +0000637 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000638 {
639 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
640 if (bytes_written > 0)
641 {
642 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
643 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000644 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000645 path);
646 return true;
647 }
648 else
649 {
650 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
651 result.SetStatus(eReturnStatusFailed);
652 return false;
653 }
654 }
655 else
656 {
657 // We are going to write ASCII to the file just point the
658 // output_stream to our outfile_stream...
659 output_stream = &outfile_stream;
660 }
661 }
662 else
663 {
Greg Clayton84c39662011-04-27 22:04:39 +0000664 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000665 result.SetStatus(eReturnStatusFailed);
666 return false;
667 }
668 }
669 else
670 {
671 output_stream = &result.GetOutputStream();
672 }
673
Greg Clayton84c39662011-04-27 22:04:39 +0000674
Greg Clayton5009f9d2011-10-27 17:55:14 +0000675 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000676 if (clang_ast_type.GetOpaqueQualType())
677 {
678 for (uint32_t i = 0; i<item_count; ++i)
679 {
680 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000681 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000682 StreamString name_strm;
683 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000684 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000685 name_strm.GetString().c_str(),
686 address,
687 clang_ast_type));
688 if (valobj_sp)
689 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000690 if (format != eFormatDefault)
691 valobj_sp->SetFormat (format);
692
Greg Clayton68ebae62011-04-28 20:55:26 +0000693 bool scope_already_checked = true;
Greg Clayton84c39662011-04-27 22:04:39 +0000694
Enrico Granata0c489f52012-03-01 04:24:26 +0000695 ValueObject::DumpValueObjectOptions options;
696 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
697 .SetMaximumDepth(m_varobj_options.max_depth)
698 .SetShowLocation(m_varobj_options.show_location)
699 .SetShowTypes(m_varobj_options.show_types)
700 .SetUseObjectiveC(m_varobj_options.use_objc)
701 .SetScopeChecked(scope_already_checked)
702 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granata86cc9822012-03-19 22:58:49 +0000703 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata0c489f52012-03-01 04:24:26 +0000704 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
705 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
706 .SetFormat(format)
707 .SetSummary();
Greg Clayton84c39662011-04-27 22:04:39 +0000708 ValueObject::DumpValueObject (*output_stream,
709 valobj_sp.get(),
Enrico Granata0c489f52012-03-01 04:24:26 +0000710 options);
Greg Clayton84c39662011-04-27 22:04:39 +0000711 }
712 else
713 {
714 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
715 view_as_type_cstr,
716 name_strm.GetString().c_str());
717 result.SetStatus(eReturnStatusFailed);
718 return false;
719 }
720 }
721 return true;
722 }
723
724 result.SetStatus(eReturnStatusSuccessFinishResult);
725 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000726 target->GetArchitecture().GetByteOrder(),
727 target->GetArchitecture().GetAddressByteSize());
Greg Clayton84c39662011-04-27 22:04:39 +0000728
729
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000730 assert (output_stream);
Greg Clayton1848afb2011-10-28 23:44:55 +0000731 uint32_t bytes_dumped = data.Dump (output_stream,
732 0,
733 m_format_options.GetFormat(),
734 item_byte_size,
735 item_count,
736 num_per_line,
737 addr,
738 0,
739 0,
740 exe_scope);
741 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000742 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000743 return true;
744 }
745
746protected:
Greg Clayton84c39662011-04-27 22:04:39 +0000747 OptionGroupOptions m_option_group;
748 OptionGroupFormat m_format_options;
749 OptionGroupReadMemory m_memory_options;
750 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000751 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000752 lldb::addr_t m_next_addr;
753 lldb::addr_t m_prev_byte_size;
754 OptionGroupFormat m_prev_format_options;
755 OptionGroupReadMemory m_prev_memory_options;
756 OptionGroupOutputFile m_prev_outfile_options;
757 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000758};
759
Greg Clayton1deb7962011-10-25 06:44:01 +0000760
761OptionDefinition
762g_memory_write_option_table[] =
763{
764{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
765{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
766};
767
768
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000769//----------------------------------------------------------------------
770// Write memory to the inferior process
771//----------------------------------------------------------------------
772class CommandObjectMemoryWrite : public CommandObject
773{
774public:
775
Greg Clayton1deb7962011-10-25 06:44:01 +0000776 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000777 {
778 public:
Greg Clayton1deb7962011-10-25 06:44:01 +0000779 OptionGroupWriteMemory () :
780 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000781 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000782 }
783
784 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +0000785 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000786 {
787 }
788
Greg Clayton1deb7962011-10-25 06:44:01 +0000789 virtual uint32_t
790 GetNumDefinitions ()
791 {
792 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
793 }
794
795 virtual const OptionDefinition*
796 GetDefinitions ()
797 {
798 return g_memory_write_option_table;
799 }
800
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000801 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000802 SetOptionValue (CommandInterpreter &interpreter,
803 uint32_t option_idx,
804 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000805 {
806 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000807 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
808
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000809 switch (short_option)
810 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000811 case 'i':
812 m_infile.SetFile (option_arg, true);
813 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000814 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000815 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +0000816 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000817 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000818 break;
819
820 case 'o':
821 {
822 bool success;
823 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
824 if (!success)
825 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000826 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +0000827 }
828 }
829 break;
830
831 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000832 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +0000833 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000834 }
835 return error;
836 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000837
838 virtual void
839 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000840 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000841 m_infile.Clear();
842 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000843 }
844
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000845 FileSpec m_infile;
846 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000847 };
848
Greg Claytona7015092010-09-18 01:14:36 +0000849 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
850 CommandObject (interpreter,
851 "memory write",
Caroline Ticee3d26312010-09-08 21:06:11 +0000852 "Write to the memory of the process being debugged.",
Caroline Tice405fe672010-10-04 22:28:36 +0000853 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
854 NULL,
Greg Claytoneb0103f2011-04-07 22:46:35 +0000855 eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +0000856 m_option_group (interpreter),
857 m_format_options (eFormatBytes, 1, UINT64_MAX),
858 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000859 {
Caroline Tice405fe672010-10-04 22:28:36 +0000860 CommandArgumentEntry arg1;
861 CommandArgumentEntry arg2;
862 CommandArgumentData addr_arg;
863 CommandArgumentData value_arg;
864
865 // Define the first (and only) variant of this arg.
866 addr_arg.arg_type = eArgTypeAddress;
867 addr_arg.arg_repetition = eArgRepeatPlain;
868
869 // There is only one variant this argument could be; put it into the argument entry.
870 arg1.push_back (addr_arg);
871
872 // Define the first (and only) variant of this arg.
873 value_arg.arg_type = eArgTypeValue;
874 value_arg.arg_repetition = eArgRepeatPlus;
875
876 // There is only one variant this argument could be; put it into the argument entry.
877 arg2.push_back (value_arg);
878
879 // Push the data for the first argument into the m_arguments vector.
880 m_arguments.push_back (arg1);
881 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +0000882
883 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
884 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
885 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
886 m_option_group.Finalize();
887
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000888 }
889
890 virtual
891 ~CommandObjectMemoryWrite ()
892 {
893 }
894
895 Options *
896 GetOptions ()
897 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000898 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000899 }
900
901 bool
902 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
903 {
904 if (total_byte_size > 8)
905 return false;
906
907 if (total_byte_size == 8)
908 return true;
909
910 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
911 return uval64 <= max;
912 }
913
914 bool
915 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
916 {
917 if (total_byte_size > 8)
918 return false;
919
920 if (total_byte_size == 8)
921 return true;
922
923 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
924 const int64_t min = ~(max);
925 return min <= sval64 && sval64 <= max;
926 }
927
928 virtual bool
Greg Claytona7015092010-09-18 01:14:36 +0000929 Execute (Args& command,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000930 CommandReturnObject &result)
931 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000932 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000933 if (process == NULL)
934 {
935 result.AppendError("need a process to read memory");
936 result.SetStatus(eReturnStatusFailed);
937 return false;
938 }
939
940 const size_t argc = command.GetArgumentCount();
941
Greg Clayton1deb7962011-10-25 06:44:01 +0000942 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000943 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000944 if (argc < 1)
945 {
946 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
947 result.SetStatus(eReturnStatusFailed);
948 return false;
949 }
950 }
951 else if (argc < 2)
952 {
953 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 +0000954 result.SetStatus(eReturnStatusFailed);
955 return false;
956 }
957
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000958 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +0000959 process->GetTarget().GetArchitecture().GetAddressByteSize(),
960 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000961
Greg Clayton1deb7962011-10-25 06:44:01 +0000962 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
963 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +0000964
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000965 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
966
967 if (addr == LLDB_INVALID_ADDRESS)
968 {
969 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
970 result.SetStatus(eReturnStatusFailed);
971 return false;
972 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000973
Greg Clayton1deb7962011-10-25 06:44:01 +0000974 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000975 {
976 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +0000977 if (item_byte_size > 0)
978 length = item_byte_size;
979 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000980 if (data_sp)
981 {
982 length = data_sp->GetByteSize();
983 if (length > 0)
984 {
985 Error error;
986 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
987
988 if (bytes_written == length)
989 {
990 // All bytes written
991 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
992 result.SetStatus(eReturnStatusSuccessFinishResult);
993 }
994 else if (bytes_written > 0)
995 {
996 // Some byte written
997 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
998 result.SetStatus(eReturnStatusSuccessFinishResult);
999 }
1000 else
1001 {
1002 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1003 result.SetStatus(eReturnStatusFailed);
1004 }
1005 }
1006 }
1007 else
1008 {
1009 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1010 result.SetStatus(eReturnStatusFailed);
1011 }
1012 return result.Succeeded();
1013 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001014 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001015 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001016 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001017 item_byte_size = buffer.GetAddressByteSize();
1018 else
1019 item_byte_size = 1;
1020 }
1021
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001022 command.Shift(); // shift off the address argument
1023 uint64_t uval64;
1024 int64_t sval64;
1025 bool success = false;
1026 const uint32_t num_value_args = command.GetArgumentCount();
1027 uint32_t i;
1028 for (i=0; i<num_value_args; ++i)
1029 {
1030 const char *value_str = command.GetArgumentAtIndex(i);
1031
Greg Clayton1deb7962011-10-25 06:44:01 +00001032 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001033 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001034 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001035 case eFormatFloat: // TODO: add support for floats soon
1036 case eFormatCharPrintable:
1037 case eFormatBytesWithASCII:
1038 case eFormatComplex:
1039 case eFormatEnum:
1040 case eFormatUnicode16:
1041 case eFormatUnicode32:
1042 case eFormatVectorOfChar:
1043 case eFormatVectorOfSInt8:
1044 case eFormatVectorOfUInt8:
1045 case eFormatVectorOfSInt16:
1046 case eFormatVectorOfUInt16:
1047 case eFormatVectorOfSInt32:
1048 case eFormatVectorOfUInt32:
1049 case eFormatVectorOfSInt64:
1050 case eFormatVectorOfUInt64:
1051 case eFormatVectorOfFloat32:
1052 case eFormatVectorOfFloat64:
1053 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001054 case eFormatOSType:
1055 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001056 case eFormatAddressInfo:
1057 case eFormatHexFloat:
1058 case eFormatInstruction:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001059 result.AppendError("unsupported format for writing memory");
1060 result.SetStatus(eReturnStatusFailed);
1061 return false;
1062
1063 case eFormatDefault:
1064 case eFormatBytes:
1065 case eFormatHex:
Greg Claytonc982c762010-07-09 20:39:50 +00001066 case eFormatPointer:
1067
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001068 // Decode hex bytes
1069 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1070 if (!success)
1071 {
1072 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1073 result.SetStatus(eReturnStatusFailed);
1074 return false;
1075 }
1076 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1077 {
Jason Molendafd54b362011-09-20 21:44:10 +00001078 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 +00001079 result.SetStatus(eReturnStatusFailed);
1080 return false;
1081 }
1082 buffer.PutMaxHex64 (uval64, item_byte_size);
1083 break;
1084
1085 case eFormatBoolean:
1086 uval64 = Args::StringToBoolean(value_str, false, &success);
1087 if (!success)
1088 {
1089 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1090 result.SetStatus(eReturnStatusFailed);
1091 return false;
1092 }
1093 buffer.PutMaxHex64 (uval64, item_byte_size);
1094 break;
1095
1096 case eFormatBinary:
1097 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1098 if (!success)
1099 {
1100 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1101 result.SetStatus(eReturnStatusFailed);
1102 return false;
1103 }
1104 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1105 {
Jason Molendafd54b362011-09-20 21:44:10 +00001106 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 +00001107 result.SetStatus(eReturnStatusFailed);
1108 return false;
1109 }
1110 buffer.PutMaxHex64 (uval64, item_byte_size);
1111 break;
1112
Greg Clayton4e4294b2011-06-17 23:50:44 +00001113 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001114 case eFormatChar:
1115 case eFormatCString:
1116 if (value_str[0])
1117 {
1118 size_t len = strlen (value_str);
1119 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001120 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001121 ++len;
1122 Error error;
1123 if (process->WriteMemory (addr, value_str, len, error) == len)
1124 {
1125 addr += len;
1126 }
1127 else
1128 {
1129 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1130 result.SetStatus(eReturnStatusFailed);
1131 return false;
1132 }
1133 }
1134 break;
1135
1136 case eFormatDecimal:
1137 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1138 if (!success)
1139 {
1140 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1141 result.SetStatus(eReturnStatusFailed);
1142 return false;
1143 }
1144 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1145 {
Jason Molendafd54b362011-09-20 21:44:10 +00001146 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 +00001147 result.SetStatus(eReturnStatusFailed);
1148 return false;
1149 }
1150 buffer.PutMaxHex64 (sval64, item_byte_size);
1151 break;
1152
1153 case eFormatUnsigned:
1154 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1155 if (!success)
1156 {
1157 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1158 result.SetStatus(eReturnStatusFailed);
1159 return false;
1160 }
1161 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1162 {
Jason Molendafd54b362011-09-20 21:44:10 +00001163 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 +00001164 result.SetStatus(eReturnStatusFailed);
1165 return false;
1166 }
1167 buffer.PutMaxHex64 (uval64, item_byte_size);
1168 break;
1169
1170 case eFormatOctal:
1171 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1172 if (!success)
1173 {
1174 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1175 result.SetStatus(eReturnStatusFailed);
1176 return false;
1177 }
1178 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1179 {
Jason Molendafd54b362011-09-20 21:44:10 +00001180 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 +00001181 result.SetStatus(eReturnStatusFailed);
1182 return false;
1183 }
1184 buffer.PutMaxHex64 (uval64, item_byte_size);
1185 break;
1186 }
1187 }
1188
1189 if (!buffer.GetString().empty())
1190 {
1191 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001192 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001193 return true;
1194 else
1195 {
1196 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1197 result.SetStatus(eReturnStatusFailed);
1198 return false;
1199 }
1200 }
1201 return true;
1202 }
1203
1204protected:
Greg Clayton1deb7962011-10-25 06:44:01 +00001205
1206 OptionGroupOptions m_option_group;
1207 OptionGroupFormat m_format_options;
1208 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001209};
1210
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001211
1212//-------------------------------------------------------------------------
1213// CommandObjectMemory
1214//-------------------------------------------------------------------------
1215
Greg Clayton66111032010-06-23 01:19:29 +00001216CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001217 CommandObjectMultiword (interpreter,
1218 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001219 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001220 "memory <subcommand> [<subcommand-options>]")
1221{
Greg Claytona7015092010-09-18 01:14:36 +00001222 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1223 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001224}
1225
1226CommandObjectMemory::~CommandObjectMemory ()
1227{
1228}