blob: 402809443a8ffb689cde209d8923e844a4275f5c [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'));
Greg Clayton3508c382012-02-24 01:59:29 +0000598 Address address(addr, NULL);
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);
Greg Clayton3508c382012-02-24 01:59:29 +0000680 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000681 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,
Greg Claytonccf44502012-01-26 21:08:30 +0000708 m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap,
709 format);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000710 }
711 else
712 {
713 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
714 view_as_type_cstr,
715 name_strm.GetString().c_str());
716 result.SetStatus(eReturnStatusFailed);
717 return false;
718 }
719 }
720 return true;
721 }
722
723 result.SetStatus(eReturnStatusSuccessFinishResult);
724 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000725 target->GetArchitecture().GetByteOrder(),
726 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000727
728
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000729 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000730 uint32_t bytes_dumped = data.Dump (output_stream,
731 0,
732 m_format_options.GetFormat(),
733 item_byte_size,
734 item_count,
735 num_per_line,
736 addr,
737 0,
738 0,
739 exe_scope);
740 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000741 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000742 return true;
743 }
744
745protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000746 OptionGroupOptions m_option_group;
747 OptionGroupFormat m_format_options;
748 OptionGroupReadMemory m_memory_options;
749 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000750 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000751 lldb::addr_t m_next_addr;
752 lldb::addr_t m_prev_byte_size;
753 OptionGroupFormat m_prev_format_options;
754 OptionGroupReadMemory m_prev_memory_options;
755 OptionGroupOutputFile m_prev_outfile_options;
756 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000757};
758
Greg Claytona42880a2011-10-25 06:44:01 +0000759
760OptionDefinition
761g_memory_write_option_table[] =
762{
763{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
764{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
765};
766
767
Chris Lattner24943d22010-06-08 16:52:24 +0000768//----------------------------------------------------------------------
769// Write memory to the inferior process
770//----------------------------------------------------------------------
771class CommandObjectMemoryWrite : public CommandObject
772{
773public:
774
Greg Claytona42880a2011-10-25 06:44:01 +0000775 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000776 {
777 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000778 OptionGroupWriteMemory () :
779 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000780 {
Chris Lattner24943d22010-06-08 16:52:24 +0000781 }
782
783 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000784 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000785 {
786 }
787
Greg Claytona42880a2011-10-25 06:44:01 +0000788 virtual uint32_t
789 GetNumDefinitions ()
790 {
791 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
792 }
793
794 virtual const OptionDefinition*
795 GetDefinitions ()
796 {
797 return g_memory_write_option_table;
798 }
799
Chris Lattner24943d22010-06-08 16:52:24 +0000800 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000801 SetOptionValue (CommandInterpreter &interpreter,
802 uint32_t option_idx,
803 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000804 {
805 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000806 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
807
Chris Lattner24943d22010-06-08 16:52:24 +0000808 switch (short_option)
809 {
Greg Claytona42880a2011-10-25 06:44:01 +0000810 case 'i':
811 m_infile.SetFile (option_arg, true);
812 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000813 {
Greg Claytona42880a2011-10-25 06:44:01 +0000814 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000815 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000816 }
Greg Claytona42880a2011-10-25 06:44:01 +0000817 break;
818
819 case 'o':
820 {
821 bool success;
822 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
823 if (!success)
824 {
Greg Clayton9c236732011-10-26 00:56:27 +0000825 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000826 }
827 }
828 break;
829
830 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000831 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000832 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000833 }
834 return error;
835 }
Greg Claytona42880a2011-10-25 06:44:01 +0000836
837 virtual void
838 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000839 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000840 m_infile.Clear();
841 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000842 }
843
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000844 FileSpec m_infile;
845 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000846 };
847
Greg Clayton238c0a12010-09-18 01:14:36 +0000848 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
849 CommandObject (interpreter,
850 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000851 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000852 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
853 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000854 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000855 m_option_group (interpreter),
856 m_format_options (eFormatBytes, 1, UINT64_MAX),
857 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000858 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000859 CommandArgumentEntry arg1;
860 CommandArgumentEntry arg2;
861 CommandArgumentData addr_arg;
862 CommandArgumentData value_arg;
863
864 // Define the first (and only) variant of this arg.
865 addr_arg.arg_type = eArgTypeAddress;
866 addr_arg.arg_repetition = eArgRepeatPlain;
867
868 // There is only one variant this argument could be; put it into the argument entry.
869 arg1.push_back (addr_arg);
870
871 // Define the first (and only) variant of this arg.
872 value_arg.arg_type = eArgTypeValue;
873 value_arg.arg_repetition = eArgRepeatPlus;
874
875 // There is only one variant this argument could be; put it into the argument entry.
876 arg2.push_back (value_arg);
877
878 // Push the data for the first argument into the m_arguments vector.
879 m_arguments.push_back (arg1);
880 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000881
882 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
883 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
884 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
885 m_option_group.Finalize();
886
Chris Lattner24943d22010-06-08 16:52:24 +0000887 }
888
889 virtual
890 ~CommandObjectMemoryWrite ()
891 {
892 }
893
894 Options *
895 GetOptions ()
896 {
Greg Claytona42880a2011-10-25 06:44:01 +0000897 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000898 }
899
900 bool
901 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
902 {
903 if (total_byte_size > 8)
904 return false;
905
906 if (total_byte_size == 8)
907 return true;
908
909 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
910 return uval64 <= max;
911 }
912
913 bool
914 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
915 {
916 if (total_byte_size > 8)
917 return false;
918
919 if (total_byte_size == 8)
920 return true;
921
922 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
923 const int64_t min = ~(max);
924 return min <= sval64 && sval64 <= max;
925 }
926
927 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000928 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000929 CommandReturnObject &result)
930 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000931 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000932 if (process == NULL)
933 {
934 result.AppendError("need a process to read memory");
935 result.SetStatus(eReturnStatusFailed);
936 return false;
937 }
938
939 const size_t argc = command.GetArgumentCount();
940
Greg Claytona42880a2011-10-25 06:44:01 +0000941 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000942 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000943 if (argc < 1)
944 {
945 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
946 result.SetStatus(eReturnStatusFailed);
947 return false;
948 }
949 }
950 else if (argc < 2)
951 {
952 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 +0000953 result.SetStatus(eReturnStatusFailed);
954 return false;
955 }
956
Chris Lattner24943d22010-06-08 16:52:24 +0000957 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000958 process->GetTarget().GetArchitecture().GetAddressByteSize(),
959 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000960
Greg Claytona42880a2011-10-25 06:44:01 +0000961 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
962 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000963
Chris Lattner24943d22010-06-08 16:52:24 +0000964 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
965
966 if (addr == LLDB_INVALID_ADDRESS)
967 {
968 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
969 result.SetStatus(eReturnStatusFailed);
970 return false;
971 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000972
Greg Claytona42880a2011-10-25 06:44:01 +0000973 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000974 {
975 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000976 if (item_byte_size > 0)
977 length = item_byte_size;
978 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000979 if (data_sp)
980 {
981 length = data_sp->GetByteSize();
982 if (length > 0)
983 {
984 Error error;
985 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
986
987 if (bytes_written == length)
988 {
989 // All bytes written
990 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
991 result.SetStatus(eReturnStatusSuccessFinishResult);
992 }
993 else if (bytes_written > 0)
994 {
995 // Some byte written
996 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
997 result.SetStatus(eReturnStatusSuccessFinishResult);
998 }
999 else
1000 {
1001 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1002 result.SetStatus(eReturnStatusFailed);
1003 }
1004 }
1005 }
1006 else
1007 {
1008 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1009 result.SetStatus(eReturnStatusFailed);
1010 }
1011 return result.Succeeded();
1012 }
Greg Claytona42880a2011-10-25 06:44:01 +00001013 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001014 {
Greg Claytona42880a2011-10-25 06:44:01 +00001015 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001016 item_byte_size = buffer.GetAddressByteSize();
1017 else
1018 item_byte_size = 1;
1019 }
1020
Chris Lattner24943d22010-06-08 16:52:24 +00001021 command.Shift(); // shift off the address argument
1022 uint64_t uval64;
1023 int64_t sval64;
1024 bool success = false;
1025 const uint32_t num_value_args = command.GetArgumentCount();
1026 uint32_t i;
1027 for (i=0; i<num_value_args; ++i)
1028 {
1029 const char *value_str = command.GetArgumentAtIndex(i);
1030
Greg Claytona42880a2011-10-25 06:44:01 +00001031 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001032 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001033 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001034 case eFormatFloat: // TODO: add support for floats soon
1035 case eFormatCharPrintable:
1036 case eFormatBytesWithASCII:
1037 case eFormatComplex:
1038 case eFormatEnum:
1039 case eFormatUnicode16:
1040 case eFormatUnicode32:
1041 case eFormatVectorOfChar:
1042 case eFormatVectorOfSInt8:
1043 case eFormatVectorOfUInt8:
1044 case eFormatVectorOfSInt16:
1045 case eFormatVectorOfUInt16:
1046 case eFormatVectorOfSInt32:
1047 case eFormatVectorOfUInt32:
1048 case eFormatVectorOfSInt64:
1049 case eFormatVectorOfUInt64:
1050 case eFormatVectorOfFloat32:
1051 case eFormatVectorOfFloat64:
1052 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001053 case eFormatOSType:
1054 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001055 case eFormatAddressInfo:
1056 case eFormatHexFloat:
1057 case eFormatInstruction:
Chris Lattner24943d22010-06-08 16:52:24 +00001058 result.AppendError("unsupported format for writing memory");
1059 result.SetStatus(eReturnStatusFailed);
1060 return false;
1061
1062 case eFormatDefault:
1063 case eFormatBytes:
1064 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001065 case eFormatPointer:
1066
Chris Lattner24943d22010-06-08 16:52:24 +00001067 // Decode hex bytes
1068 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1069 if (!success)
1070 {
1071 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1072 result.SetStatus(eReturnStatusFailed);
1073 return false;
1074 }
1075 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1076 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001077 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 +00001078 result.SetStatus(eReturnStatusFailed);
1079 return false;
1080 }
1081 buffer.PutMaxHex64 (uval64, item_byte_size);
1082 break;
1083
1084 case eFormatBoolean:
1085 uval64 = Args::StringToBoolean(value_str, false, &success);
1086 if (!success)
1087 {
1088 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1089 result.SetStatus(eReturnStatusFailed);
1090 return false;
1091 }
1092 buffer.PutMaxHex64 (uval64, item_byte_size);
1093 break;
1094
1095 case eFormatBinary:
1096 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1097 if (!success)
1098 {
1099 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1100 result.SetStatus(eReturnStatusFailed);
1101 return false;
1102 }
1103 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1104 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001105 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 +00001106 result.SetStatus(eReturnStatusFailed);
1107 return false;
1108 }
1109 buffer.PutMaxHex64 (uval64, item_byte_size);
1110 break;
1111
Greg Clayton307fa072011-06-17 23:50:44 +00001112 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001113 case eFormatChar:
1114 case eFormatCString:
1115 if (value_str[0])
1116 {
1117 size_t len = strlen (value_str);
1118 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001119 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001120 ++len;
1121 Error error;
1122 if (process->WriteMemory (addr, value_str, len, error) == len)
1123 {
1124 addr += len;
1125 }
1126 else
1127 {
1128 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1129 result.SetStatus(eReturnStatusFailed);
1130 return false;
1131 }
1132 }
1133 break;
1134
1135 case eFormatDecimal:
1136 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1137 if (!success)
1138 {
1139 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1140 result.SetStatus(eReturnStatusFailed);
1141 return false;
1142 }
1143 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1144 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001145 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 +00001146 result.SetStatus(eReturnStatusFailed);
1147 return false;
1148 }
1149 buffer.PutMaxHex64 (sval64, item_byte_size);
1150 break;
1151
1152 case eFormatUnsigned:
1153 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1154 if (!success)
1155 {
1156 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1157 result.SetStatus(eReturnStatusFailed);
1158 return false;
1159 }
1160 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1161 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001162 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 +00001163 result.SetStatus(eReturnStatusFailed);
1164 return false;
1165 }
1166 buffer.PutMaxHex64 (uval64, item_byte_size);
1167 break;
1168
1169 case eFormatOctal:
1170 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1171 if (!success)
1172 {
1173 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1174 result.SetStatus(eReturnStatusFailed);
1175 return false;
1176 }
1177 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1178 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001179 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 +00001180 result.SetStatus(eReturnStatusFailed);
1181 return false;
1182 }
1183 buffer.PutMaxHex64 (uval64, item_byte_size);
1184 break;
1185 }
1186 }
1187
1188 if (!buffer.GetString().empty())
1189 {
1190 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001191 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001192 return true;
1193 else
1194 {
1195 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1196 result.SetStatus(eReturnStatusFailed);
1197 return false;
1198 }
1199 }
1200 return true;
1201 }
1202
1203protected:
Greg Claytona42880a2011-10-25 06:44:01 +00001204
1205 OptionGroupOptions m_option_group;
1206 OptionGroupFormat m_format_options;
1207 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001208};
1209
Chris Lattner24943d22010-06-08 16:52:24 +00001210
1211//-------------------------------------------------------------------------
1212// CommandObjectMemory
1213//-------------------------------------------------------------------------
1214
Greg Clayton63094e02010-06-23 01:19:29 +00001215CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001216 CommandObjectMultiword (interpreter,
1217 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001218 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001219 "memory <subcommand> [<subcommand-options>]")
1220{
Greg Clayton238c0a12010-09-18 01:14:36 +00001221 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1222 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001223}
1224
1225CommandObjectMemory::~CommandObjectMemory ()
1226{
1227}