blob: 7a16a60bc0e52ca9b90ab35fb135cdfcf0f0bf79 [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,
326 LLDB_OPT_SET_1 | 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,
329 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | 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);
729 data.Dump (output_stream,
730 0,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000731 m_format_options.GetFormat(),
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000732 item_byte_size,
733 item_count,
734 num_per_line,
735 addr,
736 0,
Greg Clayton24a6bd92011-10-27 17:55:14 +0000737 0,
738 exe_scope);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000739 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000740 return true;
741 }
742
743protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000744 OptionGroupOptions m_option_group;
745 OptionGroupFormat m_format_options;
746 OptionGroupReadMemory m_memory_options;
747 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000748 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000749 lldb::addr_t m_next_addr;
750 lldb::addr_t m_prev_byte_size;
751 OptionGroupFormat m_prev_format_options;
752 OptionGroupReadMemory m_prev_memory_options;
753 OptionGroupOutputFile m_prev_outfile_options;
754 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000755};
756
Greg Claytona42880a2011-10-25 06:44:01 +0000757
758OptionDefinition
759g_memory_write_option_table[] =
760{
761{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
762{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
763};
764
765
Chris Lattner24943d22010-06-08 16:52:24 +0000766//----------------------------------------------------------------------
767// Write memory to the inferior process
768//----------------------------------------------------------------------
769class CommandObjectMemoryWrite : public CommandObject
770{
771public:
772
Greg Claytona42880a2011-10-25 06:44:01 +0000773 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000774 {
775 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000776 OptionGroupWriteMemory () :
777 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000778 {
Chris Lattner24943d22010-06-08 16:52:24 +0000779 }
780
781 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000782 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000783 {
784 }
785
Greg Claytona42880a2011-10-25 06:44:01 +0000786 virtual uint32_t
787 GetNumDefinitions ()
788 {
789 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
790 }
791
792 virtual const OptionDefinition*
793 GetDefinitions ()
794 {
795 return g_memory_write_option_table;
796 }
797
Chris Lattner24943d22010-06-08 16:52:24 +0000798 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000799 SetOptionValue (CommandInterpreter &interpreter,
800 uint32_t option_idx,
801 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000802 {
803 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000804 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
805
Chris Lattner24943d22010-06-08 16:52:24 +0000806 switch (short_option)
807 {
Greg Claytona42880a2011-10-25 06:44:01 +0000808 case 'i':
809 m_infile.SetFile (option_arg, true);
810 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000811 {
Greg Claytona42880a2011-10-25 06:44:01 +0000812 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000813 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000814 }
Greg Claytona42880a2011-10-25 06:44:01 +0000815 break;
816
817 case 'o':
818 {
819 bool success;
820 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
821 if (!success)
822 {
Greg Clayton9c236732011-10-26 00:56:27 +0000823 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000824 }
825 }
826 break;
827
828 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000829 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000830 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000831 }
832 return error;
833 }
Greg Claytona42880a2011-10-25 06:44:01 +0000834
835 virtual void
836 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000837 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000838 m_infile.Clear();
839 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000840 }
841
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000842 FileSpec m_infile;
843 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000844 };
845
Greg Clayton238c0a12010-09-18 01:14:36 +0000846 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
847 CommandObject (interpreter,
848 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000849 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000850 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
851 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000852 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000853 m_option_group (interpreter),
854 m_format_options (eFormatBytes, 1, UINT64_MAX),
855 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000856 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000857 CommandArgumentEntry arg1;
858 CommandArgumentEntry arg2;
859 CommandArgumentData addr_arg;
860 CommandArgumentData value_arg;
861
862 // Define the first (and only) variant of this arg.
863 addr_arg.arg_type = eArgTypeAddress;
864 addr_arg.arg_repetition = eArgRepeatPlain;
865
866 // There is only one variant this argument could be; put it into the argument entry.
867 arg1.push_back (addr_arg);
868
869 // Define the first (and only) variant of this arg.
870 value_arg.arg_type = eArgTypeValue;
871 value_arg.arg_repetition = eArgRepeatPlus;
872
873 // There is only one variant this argument could be; put it into the argument entry.
874 arg2.push_back (value_arg);
875
876 // Push the data for the first argument into the m_arguments vector.
877 m_arguments.push_back (arg1);
878 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000879
880 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
881 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
882 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
883 m_option_group.Finalize();
884
Chris Lattner24943d22010-06-08 16:52:24 +0000885 }
886
887 virtual
888 ~CommandObjectMemoryWrite ()
889 {
890 }
891
892 Options *
893 GetOptions ()
894 {
Greg Claytona42880a2011-10-25 06:44:01 +0000895 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000896 }
897
898 bool
899 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
900 {
901 if (total_byte_size > 8)
902 return false;
903
904 if (total_byte_size == 8)
905 return true;
906
907 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
908 return uval64 <= max;
909 }
910
911 bool
912 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
913 {
914 if (total_byte_size > 8)
915 return false;
916
917 if (total_byte_size == 8)
918 return true;
919
920 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
921 const int64_t min = ~(max);
922 return min <= sval64 && sval64 <= max;
923 }
924
925 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000926 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000927 CommandReturnObject &result)
928 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000929 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000930 if (process == NULL)
931 {
932 result.AppendError("need a process to read memory");
933 result.SetStatus(eReturnStatusFailed);
934 return false;
935 }
936
937 const size_t argc = command.GetArgumentCount();
938
Greg Claytona42880a2011-10-25 06:44:01 +0000939 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000940 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000941 if (argc < 1)
942 {
943 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
944 result.SetStatus(eReturnStatusFailed);
945 return false;
946 }
947 }
948 else if (argc < 2)
949 {
950 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000951 result.SetStatus(eReturnStatusFailed);
952 return false;
953 }
954
Chris Lattner24943d22010-06-08 16:52:24 +0000955 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000956 process->GetTarget().GetArchitecture().GetAddressByteSize(),
957 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000958
Greg Claytona42880a2011-10-25 06:44:01 +0000959 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
960 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000961
Chris Lattner24943d22010-06-08 16:52:24 +0000962 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
963
964 if (addr == LLDB_INVALID_ADDRESS)
965 {
966 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
967 result.SetStatus(eReturnStatusFailed);
968 return false;
969 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000970
Greg Claytona42880a2011-10-25 06:44:01 +0000971 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000972 {
973 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000974 if (item_byte_size > 0)
975 length = item_byte_size;
976 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000977 if (data_sp)
978 {
979 length = data_sp->GetByteSize();
980 if (length > 0)
981 {
982 Error error;
983 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
984
985 if (bytes_written == length)
986 {
987 // All bytes written
988 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
989 result.SetStatus(eReturnStatusSuccessFinishResult);
990 }
991 else if (bytes_written > 0)
992 {
993 // Some byte written
994 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
995 result.SetStatus(eReturnStatusSuccessFinishResult);
996 }
997 else
998 {
999 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1000 result.SetStatus(eReturnStatusFailed);
1001 }
1002 }
1003 }
1004 else
1005 {
1006 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1007 result.SetStatus(eReturnStatusFailed);
1008 }
1009 return result.Succeeded();
1010 }
Greg Claytona42880a2011-10-25 06:44:01 +00001011 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001012 {
Greg Claytona42880a2011-10-25 06:44:01 +00001013 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001014 item_byte_size = buffer.GetAddressByteSize();
1015 else
1016 item_byte_size = 1;
1017 }
1018
Chris Lattner24943d22010-06-08 16:52:24 +00001019 command.Shift(); // shift off the address argument
1020 uint64_t uval64;
1021 int64_t sval64;
1022 bool success = false;
1023 const uint32_t num_value_args = command.GetArgumentCount();
1024 uint32_t i;
1025 for (i=0; i<num_value_args; ++i)
1026 {
1027 const char *value_str = command.GetArgumentAtIndex(i);
1028
Greg Claytona42880a2011-10-25 06:44:01 +00001029 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001030 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001031 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001032 case eFormatFloat: // TODO: add support for floats soon
1033 case eFormatCharPrintable:
1034 case eFormatBytesWithASCII:
1035 case eFormatComplex:
1036 case eFormatEnum:
1037 case eFormatUnicode16:
1038 case eFormatUnicode32:
1039 case eFormatVectorOfChar:
1040 case eFormatVectorOfSInt8:
1041 case eFormatVectorOfUInt8:
1042 case eFormatVectorOfSInt16:
1043 case eFormatVectorOfUInt16:
1044 case eFormatVectorOfSInt32:
1045 case eFormatVectorOfUInt32:
1046 case eFormatVectorOfSInt64:
1047 case eFormatVectorOfUInt64:
1048 case eFormatVectorOfFloat32:
1049 case eFormatVectorOfFloat64:
1050 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001051 case eFormatOSType:
1052 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001053 case eFormatAddressInfo:
1054 case eFormatHexFloat:
1055 case eFormatInstruction:
Chris Lattner24943d22010-06-08 16:52:24 +00001056 result.AppendError("unsupported format for writing memory");
1057 result.SetStatus(eReturnStatusFailed);
1058 return false;
1059
1060 case eFormatDefault:
1061 case eFormatBytes:
1062 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001063 case eFormatPointer:
1064
Chris Lattner24943d22010-06-08 16:52:24 +00001065 // Decode hex bytes
1066 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1067 if (!success)
1068 {
1069 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1070 result.SetStatus(eReturnStatusFailed);
1071 return false;
1072 }
1073 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1074 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001075 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001076 result.SetStatus(eReturnStatusFailed);
1077 return false;
1078 }
1079 buffer.PutMaxHex64 (uval64, item_byte_size);
1080 break;
1081
1082 case eFormatBoolean:
1083 uval64 = Args::StringToBoolean(value_str, false, &success);
1084 if (!success)
1085 {
1086 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1087 result.SetStatus(eReturnStatusFailed);
1088 return false;
1089 }
1090 buffer.PutMaxHex64 (uval64, item_byte_size);
1091 break;
1092
1093 case eFormatBinary:
1094 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1095 if (!success)
1096 {
1097 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1098 result.SetStatus(eReturnStatusFailed);
1099 return false;
1100 }
1101 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1102 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001103 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001104 result.SetStatus(eReturnStatusFailed);
1105 return false;
1106 }
1107 buffer.PutMaxHex64 (uval64, item_byte_size);
1108 break;
1109
Greg Clayton307fa072011-06-17 23:50:44 +00001110 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001111 case eFormatChar:
1112 case eFormatCString:
1113 if (value_str[0])
1114 {
1115 size_t len = strlen (value_str);
1116 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001117 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001118 ++len;
1119 Error error;
1120 if (process->WriteMemory (addr, value_str, len, error) == len)
1121 {
1122 addr += len;
1123 }
1124 else
1125 {
1126 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1127 result.SetStatus(eReturnStatusFailed);
1128 return false;
1129 }
1130 }
1131 break;
1132
1133 case eFormatDecimal:
1134 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1135 if (!success)
1136 {
1137 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1138 result.SetStatus(eReturnStatusFailed);
1139 return false;
1140 }
1141 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1142 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001143 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001144 result.SetStatus(eReturnStatusFailed);
1145 return false;
1146 }
1147 buffer.PutMaxHex64 (sval64, item_byte_size);
1148 break;
1149
1150 case eFormatUnsigned:
1151 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1152 if (!success)
1153 {
1154 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1155 result.SetStatus(eReturnStatusFailed);
1156 return false;
1157 }
1158 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1159 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001160 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001161 result.SetStatus(eReturnStatusFailed);
1162 return false;
1163 }
1164 buffer.PutMaxHex64 (uval64, item_byte_size);
1165 break;
1166
1167 case eFormatOctal:
1168 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1169 if (!success)
1170 {
1171 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1172 result.SetStatus(eReturnStatusFailed);
1173 return false;
1174 }
1175 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1176 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001177 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001178 result.SetStatus(eReturnStatusFailed);
1179 return false;
1180 }
1181 buffer.PutMaxHex64 (uval64, item_byte_size);
1182 break;
1183 }
1184 }
1185
1186 if (!buffer.GetString().empty())
1187 {
1188 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001189 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001190 return true;
1191 else
1192 {
1193 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1194 result.SetStatus(eReturnStatusFailed);
1195 return false;
1196 }
1197 }
1198 return true;
1199 }
1200
1201protected:
Greg Claytona42880a2011-10-25 06:44:01 +00001202
1203 OptionGroupOptions m_option_group;
1204 OptionGroupFormat m_format_options;
1205 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001206};
1207
Chris Lattner24943d22010-06-08 16:52:24 +00001208
1209//-------------------------------------------------------------------------
1210// CommandObjectMemory
1211//-------------------------------------------------------------------------
1212
Greg Clayton63094e02010-06-23 01:19:29 +00001213CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001214 CommandObjectMultiword (interpreter,
1215 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001216 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001217 "memory <subcommand> [<subcommand-options>]")
1218{
Greg Clayton238c0a12010-09-18 01:14:36 +00001219 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1220 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001221}
1222
1223CommandObjectMemory::~CommandObjectMemory ()
1224{
1225}