blob: 95542d1d6d4e7bc0979cef2ae6d464cb39d1588b [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "CommandObjectMemory.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/DataExtractor.h"
Greg Clayton63094e02010-06-23 01:19:29 +000018#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000020#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton63094e02010-06-23 01:19:29 +000021#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton63094e02010-06-23 01:19:29 +000023#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/Options.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000025#include "lldb/Interpreter/OptionGroupFormat.h"
26#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton56bbdaf2011-04-28 20:55:26 +000027#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Sean Callanan3e80cd92011-10-12 02:08:07 +000028#include "lldb/Symbol/ClangNamespaceDecl.h"
Chris Lattner24943d22010-06-08 16:52:24 +000029#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000030#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000031
32using namespace lldb;
33using namespace lldb_private;
34
Greg Clayton56bbdaf2011-04-28 20:55:26 +000035static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000036g_option_table[] =
37{
Greg Clayton57b3c6b2011-04-27 22:04:39 +000038 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
39 { LLDB_OPT_SET_2, false, "binary" ,'b', no_argument , NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
40 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
41};
42
43
44
45class OptionGroupReadMemory : public OptionGroup
46{
47public:
48
49 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000050 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000051 m_output_as_binary (false),
52 m_view_as_type()
53 {
54 }
55
56 virtual
57 ~OptionGroupReadMemory ()
58 {
59 }
60
61
62 virtual uint32_t
63 GetNumDefinitions ()
64 {
65 return sizeof (g_option_table) / sizeof (OptionDefinition);
66 }
67
68 virtual const OptionDefinition*
69 GetDefinitions ()
70 {
71 return g_option_table;
72 }
73
74 virtual Error
75 SetOptionValue (CommandInterpreter &interpreter,
76 uint32_t option_idx,
77 const char *option_arg)
78 {
79 Error error;
80 char short_option = (char) g_option_table[option_idx].short_option;
81
82 switch (short_option)
83 {
84 case 'l':
85 error = m_num_per_line.SetValueFromCString (option_arg);
86 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000087 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000088 break;
Greg Claytona42880a2011-10-25 06:44:01 +000089
Greg Clayton57b3c6b2011-04-27 22:04:39 +000090 case 'b':
91 m_output_as_binary = true;
92 break;
93
94 case 't':
95 error = m_view_as_type.SetValueFromCString (option_arg);
96 break;
97
98 default:
Greg Clayton9c236732011-10-26 00:56:27 +000099 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000100 break;
101 }
102 return error;
103 }
104
105 virtual void
106 OptionParsingStarting (CommandInterpreter &interpreter)
107 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000108 m_num_per_line.Clear();
109 m_output_as_binary = false;
110 m_view_as_type.Clear();
111 }
112
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000113 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000114 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000115 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000116 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000117 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
118 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000119 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000120 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000121 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000122
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000123 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000124 {
125 default:
126 break;
127
128 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000129 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000130 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000131 if (!num_per_line_option_set)
132 m_num_per_line = 1;
133 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000134 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000135 break;
136
137 case eFormatCString:
138 break;
Greg Clayton24a6bd92011-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 Clayton57b3c6b2011-04-27 22:04:39 +0000154 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000155 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000156 if (!num_per_line_option_set)
157 m_num_per_line = 4;
158 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000159 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-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 Clayton24a6bd92011-10-27 17:55:14 +0000170 case eFormatHexFloat:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000171 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000172 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000173 if (!num_per_line_option_set)
174 m_num_per_line = 1;
175 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000176 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000177 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000178
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000179 case eFormatBytes:
180 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000181 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000182 {
Greg Claytona42880a2011-10-25 06:44:01 +0000183 if (byte_size_value > 1)
Greg Clayton56bbdaf2011-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 Claytona42880a2011-10-25 06:44:01 +0000187 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000188 if (!num_per_line_option_set)
189 m_num_per_line = 16;
190 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000191 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000192 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000193 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000194 case eFormatChar:
195 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000196 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000197 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000198 if (!num_per_line_option_set)
199 m_num_per_line = 32;
200 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000201 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000202 break;
203 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000204 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000205 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000206 if (!num_per_line_option_set)
207 m_num_per_line = 1;
208 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000209 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000210 break;
211 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000212 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000213 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000214 if (!num_per_line_option_set)
215 {
Greg Claytona42880a2011-10-25 06:44:01 +0000216 switch (byte_size_value)
Greg Clayton56bbdaf2011-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 Claytona42880a2011-10-25 06:44:01 +0000234 count_value = 8;
Greg Clayton57b3c6b2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000249 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000250 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000251 if (!num_per_line_option_set)
252 m_num_per_line = 1;
253 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000254 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000255 break;
256 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000257 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000258 }
259
Greg Clayton902b5be2011-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 Clayton57b3c6b2011-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 Lattner24943d22010-06-08 16:52:24 +0000275//----------------------------------------------------------------------
276// Read memory from the inferior process
277//----------------------------------------------------------------------
278class CommandObjectMemoryRead : public CommandObject
279{
280public:
281
Greg Clayton238c0a12010-09-18 01:14:36 +0000282 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
283 CommandObject (interpreter,
284 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000285 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000286 NULL,
Jim Ingham8cc3f692011-07-09 00:55:34 +0000287 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000288 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000289 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000290 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000291 m_outfile_options (),
Greg Clayton902b5be2011-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 Lattner24943d22010-06-08 16:52:24 +0000299 {
Caroline Tice43b014a2010-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 Clayton57b3c6b2011-04-27 22:04:39 +0000322
Greg Claytona42880a2011-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,
Greg Clayton31feaa82011-11-22 18:07:35 +0000326 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000327 m_option_group.Append (&m_format_options,
328 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000329 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Claytona42880a2011-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 Clayton57b3c6b2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000336 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000337 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000338 }
339
340 virtual
341 ~CommandObjectMemoryRead ()
342 {
343 }
344
345 Options *
346 GetOptions ()
347 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000348 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000349 }
350
Greg Clayton902b5be2011-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 Lattner24943d22010-06-08 16:52:24 +0000356 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000357 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000358 CommandReturnObject &result)
359 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000360 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000361 Target *target = exe_ctx.GetTargetPtr();
362 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000363 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000364 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000365 result.SetStatus(eReturnStatusFailed);
366 return false;
367 }
368 const size_t argc = command.GetArgumentCount();
369
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000370
Greg Clayton902b5be2011-10-26 04:32:38 +0000371 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-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 Clayton56bbdaf2011-04-28 20:55:26 +0000378 ClangASTType clang_ast_type;
379 Error error;
380
381 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-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 Lattner24943d22010-06-08 16:52:24 +0000384 {
Greg Clayton57b3c6b2011-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 Clayton567e7f32011-09-22 04:58:26 +0000451 StackFrame *frame = exe_ctx.GetFramePtr();
452 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000453 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000454 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000455 if (sc.module_sp)
456 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000457 sc.module_sp->FindTypes (sc,
458 lookup_type_name,
459 NULL,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000460 append,
461 1,
462 type_list);
463 }
464 }
465 if (type_list.GetSize() == 0)
466 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000467 target->GetImages().FindTypes (sc,
468 lookup_type_name,
469 append,
470 1,
471 type_list);
Greg Clayton57b3c6b2011-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 Claytona42880a2011-10-25 06:44:01 +0000500 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000501
Greg Claytona42880a2011-10-25 06:44:01 +0000502 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000509
Greg Claytona42880a2011-10-25 06:44:01 +0000510 if (!m_format_options.GetCountValue().OptionWasSet())
511 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000512 }
513 else
514 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000515 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-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 Lattner24943d22010-06-08 16:52:24 +0000524 }
525
Greg Clayton902b5be2011-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 Claytona42880a2011-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 Clayton56bbdaf2011-04-28 20:55:26 +0000548 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000549
Chris Lattner24943d22010-06-08 16:52:24 +0000550 if (total_byte_size == 0)
Greg Clayton902b5be2011-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 Lattner24943d22010-06-08 16:52:24 +0000556
Greg Clayton902b5be2011-10-26 04:32:38 +0000557 if (argc > 0)
558 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-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 Clayton56bbdaf2011-04-28 20:55:26 +0000572 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000573 result.SetStatus(eReturnStatusFailed);
574 return false;
575 }
576 else if (end_addr <= addr)
577 {
Greg Clayton56bbdaf2011-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 Lattner24943d22010-06-08 16:52:24 +0000579 result.SetStatus(eReturnStatusFailed);
580 return false;
581 }
Greg Claytona42880a2011-10-25 06:44:01 +0000582 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000583 {
Jason Molenda7e5fa7f2011-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 Lattner24943d22010-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 Clayton57b3c6b2011-04-27 22:04:39 +0000592
593 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000594 size_t bytes_read = 0;
595 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000596 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000597 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Jim Ingham8cc3f692011-07-09 00:55:34 +0000598 Address address(NULL, addr);
Greg Clayton567e7f32011-09-22 04:58:26 +0000599 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-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 Molenda7e5fa7f2011-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 Clayton902b5be2011-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 Lattner24943d22010-06-08 16:52:24 +0000619 }
620
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000621 StreamFile outfile_stream;
622 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000623 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
624 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000625 {
626 char path[PATH_MAX];
Greg Clayton57b3c6b2011-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 Claytone9f5fbd2010-10-10 20:52:20 +0000635 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000636 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-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 Clayton57b3c6b2011-04-27 22:04:39 +0000643 append ? "appended" : "written",
Greg Claytone9f5fbd2010-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 Clayton57b3c6b2011-04-27 22:04:39 +0000663 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-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 Clayton57b3c6b2011-04-27 22:04:39 +0000673
Greg Clayton24a6bd92011-10-27 17:55:14 +0000674 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-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 Clayton24a6bd92011-10-27 17:55:14 +0000683 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000684 name_strm.GetString().c_str(),
685 address,
686 clang_ast_type));
687 if (valobj_sp)
688 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000689 if (format != eFormatDefault)
690 valobj_sp->SetFormat (format);
691
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000692 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000693
694 ValueObject::DumpValueObject (*output_stream,
695 valobj_sp.get(),
696 NULL,
Greg Clayton56bbdaf2011-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 Ingham10de7d12011-05-04 03:43:18 +0000703 m_varobj_options.use_dynamic,
Enrico Granata840eb262011-08-09 23:50:01 +0000704 m_varobj_options.be_raw ? false : m_varobj_options.use_synth,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000705 scope_already_checked,
Enrico Granata7f163b32011-07-16 01:22:04 +0000706 m_varobj_options.flat_output,
Enrico Granata018921d2011-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 Clayton57b3c6b2011-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 Clayton567e7f32011-09-22 04:58:26 +0000724 target->GetArchitecture().GetByteOrder(),
725 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000726
727
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000728 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000729 uint32_t bytes_dumped = data.Dump (output_stream,
730 0,
731 m_format_options.GetFormat(),
732 item_byte_size,
733 item_count,
734 num_per_line,
735 addr,
736 0,
737 0,
738 exe_scope);
739 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000740 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000741 return true;
742 }
743
744protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000745 OptionGroupOptions m_option_group;
746 OptionGroupFormat m_format_options;
747 OptionGroupReadMemory m_memory_options;
748 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000749 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000750 lldb::addr_t m_next_addr;
751 lldb::addr_t m_prev_byte_size;
752 OptionGroupFormat m_prev_format_options;
753 OptionGroupReadMemory m_prev_memory_options;
754 OptionGroupOutputFile m_prev_outfile_options;
755 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000756};
757
Greg Claytona42880a2011-10-25 06:44:01 +0000758
759OptionDefinition
760g_memory_write_option_table[] =
761{
762{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
763{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
764};
765
766
Chris Lattner24943d22010-06-08 16:52:24 +0000767//----------------------------------------------------------------------
768// Write memory to the inferior process
769//----------------------------------------------------------------------
770class CommandObjectMemoryWrite : public CommandObject
771{
772public:
773
Greg Claytona42880a2011-10-25 06:44:01 +0000774 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000775 {
776 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000777 OptionGroupWriteMemory () :
778 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000779 {
Chris Lattner24943d22010-06-08 16:52:24 +0000780 }
781
782 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000783 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000784 {
785 }
786
Greg Claytona42880a2011-10-25 06:44:01 +0000787 virtual uint32_t
788 GetNumDefinitions ()
789 {
790 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
791 }
792
793 virtual const OptionDefinition*
794 GetDefinitions ()
795 {
796 return g_memory_write_option_table;
797 }
798
Chris Lattner24943d22010-06-08 16:52:24 +0000799 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000800 SetOptionValue (CommandInterpreter &interpreter,
801 uint32_t option_idx,
802 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000803 {
804 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000805 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
806
Chris Lattner24943d22010-06-08 16:52:24 +0000807 switch (short_option)
808 {
Greg Claytona42880a2011-10-25 06:44:01 +0000809 case 'i':
810 m_infile.SetFile (option_arg, true);
811 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000812 {
Greg Claytona42880a2011-10-25 06:44:01 +0000813 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000814 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000815 }
Greg Claytona42880a2011-10-25 06:44:01 +0000816 break;
817
818 case 'o':
819 {
820 bool success;
821 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
822 if (!success)
823 {
Greg Clayton9c236732011-10-26 00:56:27 +0000824 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000825 }
826 }
827 break;
828
829 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000830 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000831 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000832 }
833 return error;
834 }
Greg Claytona42880a2011-10-25 06:44:01 +0000835
836 virtual void
837 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000838 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000839 m_infile.Clear();
840 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000841 }
842
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000843 FileSpec m_infile;
844 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000845 };
846
Greg Clayton238c0a12010-09-18 01:14:36 +0000847 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
848 CommandObject (interpreter,
849 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000850 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000851 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
852 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000853 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000854 m_option_group (interpreter),
855 m_format_options (eFormatBytes, 1, UINT64_MAX),
856 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000857 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000858 CommandArgumentEntry arg1;
859 CommandArgumentEntry arg2;
860 CommandArgumentData addr_arg;
861 CommandArgumentData value_arg;
862
863 // Define the first (and only) variant of this arg.
864 addr_arg.arg_type = eArgTypeAddress;
865 addr_arg.arg_repetition = eArgRepeatPlain;
866
867 // There is only one variant this argument could be; put it into the argument entry.
868 arg1.push_back (addr_arg);
869
870 // Define the first (and only) variant of this arg.
871 value_arg.arg_type = eArgTypeValue;
872 value_arg.arg_repetition = eArgRepeatPlus;
873
874 // There is only one variant this argument could be; put it into the argument entry.
875 arg2.push_back (value_arg);
876
877 // Push the data for the first argument into the m_arguments vector.
878 m_arguments.push_back (arg1);
879 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000880
881 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
882 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
883 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
884 m_option_group.Finalize();
885
Chris Lattner24943d22010-06-08 16:52:24 +0000886 }
887
888 virtual
889 ~CommandObjectMemoryWrite ()
890 {
891 }
892
893 Options *
894 GetOptions ()
895 {
Greg Claytona42880a2011-10-25 06:44:01 +0000896 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000897 }
898
899 bool
900 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
901 {
902 if (total_byte_size > 8)
903 return false;
904
905 if (total_byte_size == 8)
906 return true;
907
908 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
909 return uval64 <= max;
910 }
911
912 bool
913 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
914 {
915 if (total_byte_size > 8)
916 return false;
917
918 if (total_byte_size == 8)
919 return true;
920
921 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
922 const int64_t min = ~(max);
923 return min <= sval64 && sval64 <= max;
924 }
925
926 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000927 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000928 CommandReturnObject &result)
929 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000930 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000931 if (process == NULL)
932 {
933 result.AppendError("need a process to read memory");
934 result.SetStatus(eReturnStatusFailed);
935 return false;
936 }
937
938 const size_t argc = command.GetArgumentCount();
939
Greg Claytona42880a2011-10-25 06:44:01 +0000940 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000941 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000942 if (argc < 1)
943 {
944 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
945 result.SetStatus(eReturnStatusFailed);
946 return false;
947 }
948 }
949 else if (argc < 2)
950 {
951 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000952 result.SetStatus(eReturnStatusFailed);
953 return false;
954 }
955
Chris Lattner24943d22010-06-08 16:52:24 +0000956 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000957 process->GetTarget().GetArchitecture().GetAddressByteSize(),
958 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000959
Greg Claytona42880a2011-10-25 06:44:01 +0000960 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
961 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000962
Chris Lattner24943d22010-06-08 16:52:24 +0000963 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
964
965 if (addr == LLDB_INVALID_ADDRESS)
966 {
967 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
968 result.SetStatus(eReturnStatusFailed);
969 return false;
970 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000971
Greg Claytona42880a2011-10-25 06:44:01 +0000972 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000973 {
974 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000975 if (item_byte_size > 0)
976 length = item_byte_size;
977 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000978 if (data_sp)
979 {
980 length = data_sp->GetByteSize();
981 if (length > 0)
982 {
983 Error error;
984 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
985
986 if (bytes_written == length)
987 {
988 // All bytes written
989 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
990 result.SetStatus(eReturnStatusSuccessFinishResult);
991 }
992 else if (bytes_written > 0)
993 {
994 // Some byte written
995 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
996 result.SetStatus(eReturnStatusSuccessFinishResult);
997 }
998 else
999 {
1000 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1001 result.SetStatus(eReturnStatusFailed);
1002 }
1003 }
1004 }
1005 else
1006 {
1007 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1008 result.SetStatus(eReturnStatusFailed);
1009 }
1010 return result.Succeeded();
1011 }
Greg Claytona42880a2011-10-25 06:44:01 +00001012 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001013 {
Greg Claytona42880a2011-10-25 06:44:01 +00001014 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001015 item_byte_size = buffer.GetAddressByteSize();
1016 else
1017 item_byte_size = 1;
1018 }
1019
Chris Lattner24943d22010-06-08 16:52:24 +00001020 command.Shift(); // shift off the address argument
1021 uint64_t uval64;
1022 int64_t sval64;
1023 bool success = false;
1024 const uint32_t num_value_args = command.GetArgumentCount();
1025 uint32_t i;
1026 for (i=0; i<num_value_args; ++i)
1027 {
1028 const char *value_str = command.GetArgumentAtIndex(i);
1029
Greg Claytona42880a2011-10-25 06:44:01 +00001030 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001031 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001032 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001033 case eFormatFloat: // TODO: add support for floats soon
1034 case eFormatCharPrintable:
1035 case eFormatBytesWithASCII:
1036 case eFormatComplex:
1037 case eFormatEnum:
1038 case eFormatUnicode16:
1039 case eFormatUnicode32:
1040 case eFormatVectorOfChar:
1041 case eFormatVectorOfSInt8:
1042 case eFormatVectorOfUInt8:
1043 case eFormatVectorOfSInt16:
1044 case eFormatVectorOfUInt16:
1045 case eFormatVectorOfSInt32:
1046 case eFormatVectorOfUInt32:
1047 case eFormatVectorOfSInt64:
1048 case eFormatVectorOfUInt64:
1049 case eFormatVectorOfFloat32:
1050 case eFormatVectorOfFloat64:
1051 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001052 case eFormatOSType:
1053 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001054 case eFormatAddressInfo:
1055 case eFormatHexFloat:
1056 case eFormatInstruction:
Chris Lattner24943d22010-06-08 16:52:24 +00001057 result.AppendError("unsupported format for writing memory");
1058 result.SetStatus(eReturnStatusFailed);
1059 return false;
1060
1061 case eFormatDefault:
1062 case eFormatBytes:
1063 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001064 case eFormatPointer:
1065
Chris Lattner24943d22010-06-08 16:52:24 +00001066 // Decode hex bytes
1067 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1068 if (!success)
1069 {
1070 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1071 result.SetStatus(eReturnStatusFailed);
1072 return false;
1073 }
1074 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1075 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001076 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001077 result.SetStatus(eReturnStatusFailed);
1078 return false;
1079 }
1080 buffer.PutMaxHex64 (uval64, item_byte_size);
1081 break;
1082
1083 case eFormatBoolean:
1084 uval64 = Args::StringToBoolean(value_str, false, &success);
1085 if (!success)
1086 {
1087 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1088 result.SetStatus(eReturnStatusFailed);
1089 return false;
1090 }
1091 buffer.PutMaxHex64 (uval64, item_byte_size);
1092 break;
1093
1094 case eFormatBinary:
1095 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1096 if (!success)
1097 {
1098 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1099 result.SetStatus(eReturnStatusFailed);
1100 return false;
1101 }
1102 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1103 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001104 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001105 result.SetStatus(eReturnStatusFailed);
1106 return false;
1107 }
1108 buffer.PutMaxHex64 (uval64, item_byte_size);
1109 break;
1110
Greg Clayton307fa072011-06-17 23:50:44 +00001111 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001112 case eFormatChar:
1113 case eFormatCString:
1114 if (value_str[0])
1115 {
1116 size_t len = strlen (value_str);
1117 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001118 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001119 ++len;
1120 Error error;
1121 if (process->WriteMemory (addr, value_str, len, error) == len)
1122 {
1123 addr += len;
1124 }
1125 else
1126 {
1127 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1128 result.SetStatus(eReturnStatusFailed);
1129 return false;
1130 }
1131 }
1132 break;
1133
1134 case eFormatDecimal:
1135 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1136 if (!success)
1137 {
1138 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1139 result.SetStatus(eReturnStatusFailed);
1140 return false;
1141 }
1142 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1143 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001144 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001145 result.SetStatus(eReturnStatusFailed);
1146 return false;
1147 }
1148 buffer.PutMaxHex64 (sval64, item_byte_size);
1149 break;
1150
1151 case eFormatUnsigned:
1152 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1153 if (!success)
1154 {
1155 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1156 result.SetStatus(eReturnStatusFailed);
1157 return false;
1158 }
1159 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1160 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001161 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001162 result.SetStatus(eReturnStatusFailed);
1163 return false;
1164 }
1165 buffer.PutMaxHex64 (uval64, item_byte_size);
1166 break;
1167
1168 case eFormatOctal:
1169 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1170 if (!success)
1171 {
1172 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1173 result.SetStatus(eReturnStatusFailed);
1174 return false;
1175 }
1176 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1177 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001178 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001179 result.SetStatus(eReturnStatusFailed);
1180 return false;
1181 }
1182 buffer.PutMaxHex64 (uval64, item_byte_size);
1183 break;
1184 }
1185 }
1186
1187 if (!buffer.GetString().empty())
1188 {
1189 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001190 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001191 return true;
1192 else
1193 {
1194 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1195 result.SetStatus(eReturnStatusFailed);
1196 return false;
1197 }
1198 }
1199 return true;
1200 }
1201
1202protected:
Greg Claytona42880a2011-10-25 06:44:01 +00001203
1204 OptionGroupOptions m_option_group;
1205 OptionGroupFormat m_format_options;
1206 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001207};
1208
Chris Lattner24943d22010-06-08 16:52:24 +00001209
1210//-------------------------------------------------------------------------
1211// CommandObjectMemory
1212//-------------------------------------------------------------------------
1213
Greg Clayton63094e02010-06-23 01:19:29 +00001214CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001215 CommandObjectMultiword (interpreter,
1216 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001217 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001218 "memory <subcommand> [<subcommand-options>]")
1219{
Greg Clayton238c0a12010-09-18 01:14:36 +00001220 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1221 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001222}
1223
1224CommandObjectMemory::~CommandObjectMemory ()
1225{
1226}