blob: 97ab957ff733d65003c71619e78415961dd52173 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012#include "CommandObjectMemory.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000020#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000021#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000023#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton66111032010-06-23 01:19:29 +000024#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000026#include "lldb/Interpreter/CommandInterpreter.h"
27#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000028#include "lldb/Interpreter/OptionGroupFormat.h"
29#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000030#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000031#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton1f746072012-08-29 21:13:06 +000032#include "lldb/Symbol/TypeList.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033#include "lldb/Target/Process.h"
Greg Clayton84c39662011-04-27 22:04:39 +000034#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035
36using namespace lldb;
37using namespace lldb_private;
38
Greg Clayton68ebae62011-04-28 20:55:26 +000039static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000040g_option_table[] =
41{
Greg Clayton84c39662011-04-27 22:04:39 +000042 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
43 { 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."},
Sean Callanan3d654b32012-09-24 22:25:51 +000044 { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton2346fcf2012-11-02 21:14:58 +000045 { LLDB_OPT_SET_1|
46 LLDB_OPT_SET_2|
Enrico Granatad325bf92013-06-04 22:54:16 +000047 LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
Greg Clayton84c39662011-04-27 22:04:39 +000048};
49
50
51
52class OptionGroupReadMemory : public OptionGroup
53{
54public:
55
56 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000057 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000058 m_output_as_binary (false),
59 m_view_as_type()
60 {
61 }
62
63 virtual
64 ~OptionGroupReadMemory ()
65 {
66 }
67
68
69 virtual uint32_t
70 GetNumDefinitions ()
71 {
72 return sizeof (g_option_table) / sizeof (OptionDefinition);
73 }
74
75 virtual const OptionDefinition*
76 GetDefinitions ()
77 {
78 return g_option_table;
79 }
80
81 virtual Error
82 SetOptionValue (CommandInterpreter &interpreter,
83 uint32_t option_idx,
84 const char *option_arg)
85 {
86 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000087 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000088
89 switch (short_option)
90 {
91 case 'l':
92 error = m_num_per_line.SetValueFromCString (option_arg);
93 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +000094 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +000095 break;
Greg Clayton1deb7962011-10-25 06:44:01 +000096
Greg Clayton84c39662011-04-27 22:04:39 +000097 case 'b':
98 m_output_as_binary = true;
99 break;
100
101 case 't':
102 error = m_view_as_type.SetValueFromCString (option_arg);
103 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000104
105 case 'r':
106 m_force = true;
107 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000108
109 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000110 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000111 break;
112 }
113 return error;
114 }
115
116 virtual void
117 OptionParsingStarting (CommandInterpreter &interpreter)
118 {
Greg Clayton84c39662011-04-27 22:04:39 +0000119 m_num_per_line.Clear();
120 m_output_as_binary = false;
121 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000122 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000123 }
124
Greg Clayton68ebae62011-04-28 20:55:26 +0000125 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000126 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000127 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000128 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000129 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
130 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000131 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000132 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000133 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000134
Greg Clayton68ebae62011-04-28 20:55:26 +0000135 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000136 {
137 default:
138 break;
139
140 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000141 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000142 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000143 if (!num_per_line_option_set)
144 m_num_per_line = 1;
145 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000146 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000147 break;
148
149 case eFormatCString:
150 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000151
152 case eFormatInstruction:
153 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000154 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000155 m_num_per_line = 1;
156 break;
157
158 case eFormatAddressInfo:
159 if (!byte_size_option_set)
160 byte_size_value = target->GetArchitecture().GetAddressByteSize();
161 m_num_per_line = 1;
162 if (!count_option_set)
163 format_options.GetCountValue() = 8;
164 break;
165
Greg Clayton84c39662011-04-27 22:04:39 +0000166 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000167 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000168 if (!num_per_line_option_set)
169 m_num_per_line = 4;
170 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000171 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000172 break;
173
174 case eFormatBinary:
175 case eFormatFloat:
176 case eFormatOctal:
177 case eFormatDecimal:
178 case eFormatEnum:
179 case eFormatUnicode16:
180 case eFormatUnicode32:
181 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000182 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000183 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000184 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000185 if (!num_per_line_option_set)
186 m_num_per_line = 1;
187 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000188 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000189 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000190
Greg Clayton84c39662011-04-27 22:04:39 +0000191 case eFormatBytes:
192 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000193 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000194 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000195 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000196 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000197 "\tconsider using a different display format or don't specify the byte size",
198 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000199 }
200 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000201 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000202 if (!num_per_line_option_set)
203 m_num_per_line = 16;
204 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000205 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000206 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000207 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000208 case eFormatChar:
209 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000210 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000211 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000212 if (!num_per_line_option_set)
213 m_num_per_line = 32;
214 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000215 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000216 break;
217 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000218 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000219 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000220 if (!num_per_line_option_set)
221 m_num_per_line = 1;
222 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000223 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000224 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000225 case eFormatComplexInteger:
226 if (!byte_size_option_set)
227 byte_size_value = 8;
228 if (!num_per_line_option_set)
229 m_num_per_line = 1;
230 if (!count_option_set)
231 format_options.GetCountValue() = 8;
232 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000233 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000234 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000235 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000236 if (!num_per_line_option_set)
237 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000238 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000239 {
240 case 1:
241 case 2:
242 m_num_per_line = 8;
243 break;
244 case 4:
245 m_num_per_line = 4;
246 break;
247 case 8:
248 m_num_per_line = 2;
249 break;
250 default:
251 m_num_per_line = 1;
252 break;
253 }
254 }
255 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000256 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000257 break;
258
259 case eFormatVectorOfChar:
260 case eFormatVectorOfSInt8:
261 case eFormatVectorOfUInt8:
262 case eFormatVectorOfSInt16:
263 case eFormatVectorOfUInt16:
264 case eFormatVectorOfSInt32:
265 case eFormatVectorOfUInt32:
266 case eFormatVectorOfSInt64:
267 case eFormatVectorOfUInt64:
268 case eFormatVectorOfFloat32:
269 case eFormatVectorOfFloat64:
270 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000271 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000272 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000273 if (!num_per_line_option_set)
274 m_num_per_line = 1;
275 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000276 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000277 break;
278 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000279 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000280 }
281
Greg Clayton82f4cf42011-10-26 04:32:38 +0000282 bool
283 AnyOptionWasSet () const
284 {
285 return m_num_per_line.OptionWasSet() ||
286 m_output_as_binary ||
287 m_view_as_type.OptionWasSet();
288 }
289
Greg Clayton84c39662011-04-27 22:04:39 +0000290 OptionValueUInt64 m_num_per_line;
291 bool m_output_as_binary;
292 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000293 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000294};
295
296
297
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000298//----------------------------------------------------------------------
299// Read memory from the inferior process
300//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000301class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000302{
303public:
304
Greg Claytona7015092010-09-18 01:14:36 +0000305 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000306 CommandObjectParsed (interpreter,
307 "memory read",
308 "Read from the memory of the process being debugged.",
309 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000310 eFlagRequiresTarget | eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000311 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000312 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000313 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000314 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000315 m_varobj_options(),
316 m_next_addr(LLDB_INVALID_ADDRESS),
317 m_prev_byte_size(0),
318 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
319 m_prev_memory_options (),
320 m_prev_outfile_options (),
321 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000322 {
Caroline Tice405fe672010-10-04 22:28:36 +0000323 CommandArgumentEntry arg1;
324 CommandArgumentEntry arg2;
325 CommandArgumentData start_addr_arg;
326 CommandArgumentData end_addr_arg;
327
328 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000329 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000330 start_addr_arg.arg_repetition = eArgRepeatPlain;
331
332 // There is only one variant this argument could be; put it into the argument entry.
333 arg1.push_back (start_addr_arg);
334
335 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000336 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000337 end_addr_arg.arg_repetition = eArgRepeatOptional;
338
339 // There is only one variant this argument could be; put it into the argument entry.
340 arg2.push_back (end_addr_arg);
341
342 // Push the data for the first argument into the m_arguments vector.
343 m_arguments.push_back (arg1);
344 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000345
Greg Clayton1deb7962011-10-25 06:44:01 +0000346 // Add the "--format" and "--count" options to group 1 and 3
347 m_option_group.Append (&m_format_options,
348 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000349 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000350 m_option_group.Append (&m_format_options,
351 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000352 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000353 // Add the "--size" option to group 1 and 2
354 m_option_group.Append (&m_format_options,
355 OptionGroupFormat::OPTION_GROUP_SIZE,
356 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000357 m_option_group.Append (&m_memory_options);
358 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton68ebae62011-04-28 20:55:26 +0000359 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000360 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000361 }
362
363 virtual
364 ~CommandObjectMemoryRead ()
365 {
366 }
367
368 Options *
369 GetOptions ()
370 {
Greg Clayton84c39662011-04-27 22:04:39 +0000371 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000372 }
373
Greg Clayton82f4cf42011-10-26 04:32:38 +0000374 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
375 {
376 return m_cmd_name.c_str();
377 }
378
Jim Ingham5a988412012-06-08 21:56:10 +0000379protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000381 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000382 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000383 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
384 Target *target = m_exe_ctx.GetTargetPtr();
385
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000386 const size_t argc = command.GetArgumentCount();
387
Greg Clayton82f4cf42011-10-26 04:32:38 +0000388 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000389 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000390 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
Greg Clayton2e1f7452012-12-15 02:08:17 +0000391 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392 result.SetStatus(eReturnStatusFailed);
393 return false;
394 }
395
Greg Clayton68ebae62011-04-28 20:55:26 +0000396 ClangASTType clang_ast_type;
397 Error error;
398
Greg Clayton84c39662011-04-27 22:04:39 +0000399 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
400 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000401 {
Greg Clayton84c39662011-04-27 22:04:39 +0000402 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000403
Greg Clayton84c39662011-04-27 22:04:39 +0000404 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000405 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000406 TypeList type_list;
407 uint32_t reference_count = 0;
408 uint32_t pointer_count = 0;
409 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000410
411#define ALL_KEYWORDS \
412 KEYWORD("const") \
413 KEYWORD("volatile") \
414 KEYWORD("restrict") \
415 KEYWORD("struct") \
416 KEYWORD("class") \
417 KEYWORD("union")
418
419#define KEYWORD(s) s,
420 static const char *g_keywords[] =
421 {
422 ALL_KEYWORDS
423 };
424#undef KEYWORD
425
426#define KEYWORD(s) (sizeof(s) - 1),
427 static const int g_keyword_lengths[] =
428 {
429 ALL_KEYWORDS
430 };
431#undef KEYWORD
432
433#undef ALL_KEYWORDS
434
435 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000436 std::string type_str(view_as_type_cstr);
437
438 // Remove all instances of g_keywords that are followed by spaces
439 for (size_t i = 0; i < g_num_keywords; ++i)
440 {
441 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000442 int keyword_len = g_keyword_lengths[i];
443
444 idx = 0;
445 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000446 {
447 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000448 {
Greg Clayton84c39662011-04-27 22:04:39 +0000449 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000450 idx = 0;
451 }
452 else
453 {
454 idx += keyword_len;
455 }
Greg Clayton84c39662011-04-27 22:04:39 +0000456 }
457 }
458 bool done = type_str.empty();
459 //
460 idx = type_str.find_first_not_of (" \t");
461 if (idx > 0 && idx != std::string::npos)
462 type_str.erase (0, idx);
463 while (!done)
464 {
465 // Strip trailing spaces
466 if (type_str.empty())
467 done = true;
468 else
469 {
470 switch (type_str[type_str.size()-1])
471 {
472 case '*':
473 ++pointer_count;
474 // fall through...
475 case ' ':
476 case '\t':
477 type_str.erase(type_str.size()-1);
478 break;
479
480 case '&':
481 if (reference_count == 0)
482 {
483 reference_count = 1;
484 type_str.erase(type_str.size()-1);
485 }
486 else
487 {
488 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
489 result.SetStatus(eReturnStatusFailed);
490 return false;
491 }
492 break;
493
494 default:
495 done = true;
496 break;
497 }
498 }
499 }
500
501 ConstString lookup_type_name(type_str.c_str());
Greg Claytonf9fc6092013-01-09 19:44:40 +0000502 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000503 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000504 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000505 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000506 if (sc.module_sp)
507 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000508 sc.module_sp->FindTypes (sc,
509 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000510 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000511 1,
512 type_list);
513 }
514 }
515 if (type_list.GetSize() == 0)
516 {
Greg Clayton29399a22012-04-06 17:41:13 +0000517 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000518 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000519 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000520 1,
521 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000522 }
523
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000524 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000525 {
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000526 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
527 if (tdecl)
528 {
529 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
530 }
Greg Clayton84c39662011-04-27 22:04:39 +0000531 }
532
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000533 if (clang_ast_type.IsValid() == false)
534 {
535 if (type_list.GetSize() == 0)
536 {
537 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
538 lookup_type_name.GetCString(),
539 view_as_type_cstr);
540 result.SetStatus(eReturnStatusFailed);
541 return false;
542 }
543 else
544 {
545 TypeSP type_sp (type_list.GetTypeAtIndex(0));
546 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
547 }
548 }
Greg Clayton84c39662011-04-27 22:04:39 +0000549
550 while (pointer_count > 0)
551 {
552 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
553 if (pointer_type)
554 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
555 else
556 {
557 result.AppendError ("unable make a pointer type\n");
558 result.SetStatus(eReturnStatusFailed);
559 return false;
560 }
561 --pointer_count;
562 }
563
Greg Claytonfaac1112013-03-14 18:31:44 +0000564 m_format_options.GetByteSizeValue() = clang_ast_type.GetClangTypeByteSize();
Greg Clayton84c39662011-04-27 22:04:39 +0000565
Greg Clayton1deb7962011-10-25 06:44:01 +0000566 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000567 {
568 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
569 view_as_type_cstr);
570 result.SetStatus(eReturnStatusFailed);
571 return false;
572 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000573
Greg Clayton1deb7962011-10-25 06:44:01 +0000574 if (!m_format_options.GetCountValue().OptionWasSet())
575 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000576 }
577 else
578 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000579 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000580 }
581
582 // Look for invalid combinations of settings
583 if (error.Fail())
584 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000585 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000586 result.SetStatus(eReturnStatusFailed);
587 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000588 }
589
Greg Clayton82f4cf42011-10-26 04:32:38 +0000590 lldb::addr_t addr;
591 size_t total_byte_size = 0;
592 if (argc == 0)
593 {
594 // Use the last address and byte size and all options as they were
595 // if no options have been set
596 addr = m_next_addr;
597 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000598 clang_ast_type = m_prev_clang_ast_type;
599 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000600 !m_memory_options.AnyOptionWasSet() &&
601 !m_outfile_options.AnyOptionWasSet() &&
602 !m_varobj_options.AnyOptionWasSet())
603 {
604 m_format_options = m_prev_format_options;
605 m_memory_options = m_prev_memory_options;
606 m_outfile_options = m_prev_outfile_options;
607 m_varobj_options = m_prev_varobj_options;
608 }
609 }
610
Greg Clayton1deb7962011-10-25 06:44:01 +0000611 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000612 size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000613 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000614
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000615 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000616 {
617 total_byte_size = item_count * item_byte_size;
618 if (total_byte_size == 0)
619 total_byte_size = 32;
620 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000621
Greg Clayton82f4cf42011-10-26 04:32:38 +0000622 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000623 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000624
625 if (addr == LLDB_INVALID_ADDRESS)
626 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000627 result.AppendError("invalid start address expression.");
628 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000629 result.SetStatus(eReturnStatusFailed);
630 return false;
631 }
632
633 if (argc == 2)
634 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000635 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000636 if (end_addr == LLDB_INVALID_ADDRESS)
637 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000638 result.AppendError("invalid end address expression.");
639 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000640 result.SetStatus(eReturnStatusFailed);
641 return false;
642 }
643 else if (end_addr <= addr)
644 {
Daniel Malead01b2952012-11-29 21:49:15 +0000645 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000646 result.SetStatus(eReturnStatusFailed);
647 return false;
648 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000649 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000650 {
Daniel Malead01b2952012-11-29 21:49:15 +0000651 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000652 result.SetStatus(eReturnStatusFailed);
653 return false;
654 }
655
656 total_byte_size = end_addr - addr;
657 item_count = total_byte_size / item_byte_size;
658 }
Greg Clayton84c39662011-04-27 22:04:39 +0000659
Enrico Granatad325bf92013-06-04 22:54:16 +0000660 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
661
662 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000663 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000664 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
665 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
666 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
Sean Callanan1276c332012-04-28 01:27:38 +0000667 return false;
668 }
669
Greg Clayton84c39662011-04-27 22:04:39 +0000670 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000671 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000672 if (clang_ast_type.GetOpaqueQualType())
673 {
674 // Make sure we don't display our type as ASCII bytes like the default memory read
675 if (m_format_options.GetFormatValue().OptionWasSet() == false)
676 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
677
678 bytes_read = clang_ast_type.GetTypeByteSize() * m_format_options.GetCountValue().GetCurrentValue();
679 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000680 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000681 {
Greg Clayton84c39662011-04-27 22:04:39 +0000682 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Claytone72dfb32012-02-24 01:59:29 +0000683 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000684 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000685 if (bytes_read == 0)
686 {
Greg Clayton57f06302012-05-25 17:05:55 +0000687 const char *error_cstr = error.AsCString();
688 if (error_cstr && error_cstr[0])
689 {
690 result.AppendError(error_cstr);
691 }
692 else
693 {
Daniel Malead01b2952012-11-29 21:49:15 +0000694 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000695 }
Greg Clayton84c39662011-04-27 22:04:39 +0000696 result.SetStatus(eReturnStatusFailed);
697 return false;
698 }
699
700 if (bytes_read < total_byte_size)
Jim Ingham9d8dd4b2013-01-25 23:05:01 +0000701 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000702 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000703 else
704 {
705 // we treat c-strings as a special case because they do not have a fixed size
706 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
707 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
708 else
709 item_byte_size = target->GetMaximumSizeOfStringSummary();
710 if (!m_format_options.GetCountValue().OptionWasSet())
711 item_count = 1;
712 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
713 uint8_t *data_ptr = data_sp->GetBytes();
714 auto data_addr = addr;
715 auto count = item_count;
716 item_count = 0;
717 while (item_count < count)
718 {
719 std::string buffer;
720 buffer.resize(item_byte_size+1,0);
721 Error error;
722 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
723 if (error.Fail())
724 {
725 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
726 result.SetStatus(eReturnStatusFailed);
727 return false;
728 }
729 if (item_byte_size == read)
730 {
731 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
732 break;
733 }
734 read+=1; // account for final NULL byte
735 memcpy(data_ptr, &buffer[0], read);
736 data_ptr += read;
737 data_addr += read;
738 bytes_read += read;
739 item_count++; // if we break early we know we only read item_count strings
740 }
741 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
742 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000743
Greg Clayton2e1f7452012-12-15 02:08:17 +0000744 m_next_addr = addr + bytes_read;
745 m_prev_byte_size = bytes_read;
746 m_prev_format_options = m_format_options;
747 m_prev_memory_options = m_memory_options;
748 m_prev_outfile_options = m_outfile_options;
749 m_prev_varobj_options = m_varobj_options;
750 m_prev_clang_ast_type = clang_ast_type;
751
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000752 StreamFile outfile_stream;
753 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000754 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
755 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000756 {
757 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000758 outfile_spec.GetPath (path, sizeof(path));
759
760 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
761 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
762 if (append)
763 open_options |= File::eOpenOptionAppend;
764
765 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000766 {
Greg Clayton84c39662011-04-27 22:04:39 +0000767 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000768 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000769 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000770 if (bytes_written > 0)
771 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000772 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000773 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000774 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000775 path);
776 return true;
777 }
778 else
779 {
Daniel Malead01b2952012-11-29 21:49:15 +0000780 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000781 result.SetStatus(eReturnStatusFailed);
782 return false;
783 }
784 }
785 else
786 {
787 // We are going to write ASCII to the file just point the
788 // output_stream to our outfile_stream...
789 output_stream = &outfile_stream;
790 }
791 }
792 else
793 {
Greg Clayton84c39662011-04-27 22:04:39 +0000794 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000795 result.SetStatus(eReturnStatusFailed);
796 return false;
797 }
798 }
799 else
800 {
801 output_stream = &result.GetOutputStream();
802 }
803
Greg Clayton84c39662011-04-27 22:04:39 +0000804
Greg Claytonf9fc6092013-01-09 19:44:40 +0000805 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000806 if (clang_ast_type.GetOpaqueQualType())
807 {
808 for (uint32_t i = 0; i<item_count; ++i)
809 {
810 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000811 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000812 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000813 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000814 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000815 name_strm.GetString().c_str(),
816 address,
817 clang_ast_type));
818 if (valobj_sp)
819 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000820 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000821 if (format != eFormatDefault)
822 valobj_sp->SetFormat (format);
823
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000824 ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format));
825
Greg Clayton84c39662011-04-27 22:04:39 +0000826 ValueObject::DumpValueObject (*output_stream,
827 valobj_sp.get(),
Enrico Granata0c489f52012-03-01 04:24:26 +0000828 options);
Greg Clayton84c39662011-04-27 22:04:39 +0000829 }
830 else
831 {
832 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
833 view_as_type_cstr,
834 name_strm.GetString().c_str());
835 result.SetStatus(eReturnStatusFailed);
836 return false;
837 }
838 }
839 return true;
840 }
841
842 result.SetStatus(eReturnStatusSuccessFinishResult);
843 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000844 target->GetArchitecture().GetByteOrder(),
845 target->GetArchitecture().GetAddressByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000846
847 Format format = m_format_options.GetFormat();
848 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
849 && (item_byte_size != 1)
850 && (item_count == 1))
851 {
852 // this turns requests such as
853 // memory read -fc -s10 -c1 *charPtrPtr
854 // which make no sense (what is a char of size 10?)
855 // into a request for fetching 10 chars of size 1 from the same memory location
856 format = eFormatCharArray;
857 item_count = item_byte_size;
858 item_byte_size = 1;
859 }
Greg Clayton84c39662011-04-27 22:04:39 +0000860
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000861 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000862 size_t bytes_dumped = data.Dump (output_stream,
863 0,
Enrico Granata31898912013-05-21 17:39:04 +0000864 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000865 item_byte_size,
866 item_count,
867 num_per_line,
868 addr,
869 0,
870 0,
871 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000872 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000873 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000874 return true;
875 }
876
Greg Clayton84c39662011-04-27 22:04:39 +0000877 OptionGroupOptions m_option_group;
878 OptionGroupFormat m_format_options;
879 OptionGroupReadMemory m_memory_options;
880 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000881 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000882 lldb::addr_t m_next_addr;
883 lldb::addr_t m_prev_byte_size;
884 OptionGroupFormat m_prev_format_options;
885 OptionGroupReadMemory m_prev_memory_options;
886 OptionGroupOutputFile m_prev_outfile_options;
887 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000888 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000889};
890
Greg Clayton1deb7962011-10-25 06:44:01 +0000891
892OptionDefinition
893g_memory_write_option_table[] =
894{
895{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
896{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
897};
898
899
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000900//----------------------------------------------------------------------
901// Write memory to the inferior process
902//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000903class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000904{
905public:
906
Greg Clayton1deb7962011-10-25 06:44:01 +0000907 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000908 {
909 public:
Greg Clayton1deb7962011-10-25 06:44:01 +0000910 OptionGroupWriteMemory () :
911 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000912 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000913 }
914
915 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +0000916 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000917 {
918 }
919
Greg Clayton1deb7962011-10-25 06:44:01 +0000920 virtual uint32_t
921 GetNumDefinitions ()
922 {
923 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
924 }
925
926 virtual const OptionDefinition*
927 GetDefinitions ()
928 {
929 return g_memory_write_option_table;
930 }
931
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000932 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000933 SetOptionValue (CommandInterpreter &interpreter,
934 uint32_t option_idx,
935 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000936 {
937 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000938 const int short_option = g_memory_write_option_table[option_idx].short_option;
Greg Clayton1deb7962011-10-25 06:44:01 +0000939
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000940 switch (short_option)
941 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000942 case 'i':
943 m_infile.SetFile (option_arg, true);
944 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000945 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000946 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +0000947 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000948 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000949 break;
950
951 case 'o':
952 {
953 bool success;
954 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
955 if (!success)
956 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000957 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +0000958 }
959 }
960 break;
961
962 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000963 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +0000964 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000965 }
966 return error;
967 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000968
969 virtual void
970 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000971 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000972 m_infile.Clear();
973 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000974 }
975
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000976 FileSpec m_infile;
977 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000978 };
979
Greg Claytona7015092010-09-18 01:14:36 +0000980 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000981 CommandObjectParsed (interpreter,
982 "memory write",
983 "Write to the memory of the process being debugged.",
984 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000985 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +0000986 m_option_group (interpreter),
987 m_format_options (eFormatBytes, 1, UINT64_MAX),
988 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000989 {
Caroline Tice405fe672010-10-04 22:28:36 +0000990 CommandArgumentEntry arg1;
991 CommandArgumentEntry arg2;
992 CommandArgumentData addr_arg;
993 CommandArgumentData value_arg;
994
995 // Define the first (and only) variant of this arg.
996 addr_arg.arg_type = eArgTypeAddress;
997 addr_arg.arg_repetition = eArgRepeatPlain;
998
999 // There is only one variant this argument could be; put it into the argument entry.
1000 arg1.push_back (addr_arg);
1001
1002 // Define the first (and only) variant of this arg.
1003 value_arg.arg_type = eArgTypeValue;
1004 value_arg.arg_repetition = eArgRepeatPlus;
1005
1006 // There is only one variant this argument could be; put it into the argument entry.
1007 arg2.push_back (value_arg);
1008
1009 // Push the data for the first argument into the m_arguments vector.
1010 m_arguments.push_back (arg1);
1011 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001012
1013 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1014 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1015 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1016 m_option_group.Finalize();
1017
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001018 }
1019
1020 virtual
1021 ~CommandObjectMemoryWrite ()
1022 {
1023 }
1024
1025 Options *
1026 GetOptions ()
1027 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001028 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001029 }
1030
1031 bool
1032 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1033 {
1034 if (total_byte_size > 8)
1035 return false;
1036
1037 if (total_byte_size == 8)
1038 return true;
1039
1040 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1041 return uval64 <= max;
1042 }
1043
1044 bool
1045 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1046 {
1047 if (total_byte_size > 8)
1048 return false;
1049
1050 if (total_byte_size == 8)
1051 return true;
1052
1053 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1054 const int64_t min = ~(max);
1055 return min <= sval64 && sval64 <= max;
1056 }
1057
Jim Ingham5a988412012-06-08 21:56:10 +00001058protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001059 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001060 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001061 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001062 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1063 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001064
1065 const size_t argc = command.GetArgumentCount();
1066
Greg Clayton1deb7962011-10-25 06:44:01 +00001067 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001068 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001069 if (argc < 1)
1070 {
1071 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1072 result.SetStatus(eReturnStatusFailed);
1073 return false;
1074 }
1075 }
1076 else if (argc < 2)
1077 {
1078 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001079 result.SetStatus(eReturnStatusFailed);
1080 return false;
1081 }
1082
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001083 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001084 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1085 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001086
Greg Clayton1deb7962011-10-25 06:44:01 +00001087 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1088 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001089
Greg Claytonb9d5df52012-12-06 22:49:16 +00001090 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001091 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001092 command.GetArgumentAtIndex(0),
1093 LLDB_INVALID_ADDRESS,
1094 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001095
1096 if (addr == LLDB_INVALID_ADDRESS)
1097 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001098 result.AppendError("invalid address expression\n");
1099 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001100 result.SetStatus(eReturnStatusFailed);
1101 return false;
1102 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001103
Greg Clayton1deb7962011-10-25 06:44:01 +00001104 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001105 {
1106 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +00001107 if (item_byte_size > 0)
1108 length = item_byte_size;
1109 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001110 if (data_sp)
1111 {
1112 length = data_sp->GetByteSize();
1113 if (length > 0)
1114 {
1115 Error error;
1116 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1117
1118 if (bytes_written == length)
1119 {
1120 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001121 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001122 result.SetStatus(eReturnStatusSuccessFinishResult);
1123 }
1124 else if (bytes_written > 0)
1125 {
1126 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001127 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001128 result.SetStatus(eReturnStatusSuccessFinishResult);
1129 }
1130 else
1131 {
Daniel Malead01b2952012-11-29 21:49:15 +00001132 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001133 result.SetStatus(eReturnStatusFailed);
1134 }
1135 }
1136 }
1137 else
1138 {
1139 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1140 result.SetStatus(eReturnStatusFailed);
1141 }
1142 return result.Succeeded();
1143 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001144 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001145 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001146 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001147 item_byte_size = buffer.GetAddressByteSize();
1148 else
1149 item_byte_size = 1;
1150 }
1151
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001152 command.Shift(); // shift off the address argument
1153 uint64_t uval64;
1154 int64_t sval64;
1155 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001156 const size_t num_value_args = command.GetArgumentCount();
1157 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001158 {
1159 const char *value_str = command.GetArgumentAtIndex(i);
1160
Greg Clayton1deb7962011-10-25 06:44:01 +00001161 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001162 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001163 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001164 case eFormatFloat: // TODO: add support for floats soon
1165 case eFormatCharPrintable:
1166 case eFormatBytesWithASCII:
1167 case eFormatComplex:
1168 case eFormatEnum:
1169 case eFormatUnicode16:
1170 case eFormatUnicode32:
1171 case eFormatVectorOfChar:
1172 case eFormatVectorOfSInt8:
1173 case eFormatVectorOfUInt8:
1174 case eFormatVectorOfSInt16:
1175 case eFormatVectorOfUInt16:
1176 case eFormatVectorOfSInt32:
1177 case eFormatVectorOfUInt32:
1178 case eFormatVectorOfSInt64:
1179 case eFormatVectorOfUInt64:
1180 case eFormatVectorOfFloat32:
1181 case eFormatVectorOfFloat64:
1182 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001183 case eFormatOSType:
1184 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001185 case eFormatAddressInfo:
1186 case eFormatHexFloat:
1187 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001188 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001189 result.AppendError("unsupported format for writing memory");
1190 result.SetStatus(eReturnStatusFailed);
1191 return false;
1192
1193 case eFormatDefault:
1194 case eFormatBytes:
1195 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001196 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001197 case eFormatPointer:
1198
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001199 // Decode hex bytes
1200 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1201 if (!success)
1202 {
1203 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1204 result.SetStatus(eReturnStatusFailed);
1205 return false;
1206 }
1207 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1208 {
Daniel Malead01b2952012-11-29 21:49:15 +00001209 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001210 result.SetStatus(eReturnStatusFailed);
1211 return false;
1212 }
1213 buffer.PutMaxHex64 (uval64, item_byte_size);
1214 break;
1215
1216 case eFormatBoolean:
1217 uval64 = Args::StringToBoolean(value_str, false, &success);
1218 if (!success)
1219 {
1220 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1221 result.SetStatus(eReturnStatusFailed);
1222 return false;
1223 }
1224 buffer.PutMaxHex64 (uval64, item_byte_size);
1225 break;
1226
1227 case eFormatBinary:
1228 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1229 if (!success)
1230 {
1231 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1232 result.SetStatus(eReturnStatusFailed);
1233 return false;
1234 }
1235 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1236 {
Daniel Malead01b2952012-11-29 21:49:15 +00001237 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001238 result.SetStatus(eReturnStatusFailed);
1239 return false;
1240 }
1241 buffer.PutMaxHex64 (uval64, item_byte_size);
1242 break;
1243
Greg Clayton4e4294b2011-06-17 23:50:44 +00001244 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001245 case eFormatChar:
1246 case eFormatCString:
1247 if (value_str[0])
1248 {
1249 size_t len = strlen (value_str);
1250 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001251 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001252 ++len;
1253 Error error;
1254 if (process->WriteMemory (addr, value_str, len, error) == len)
1255 {
1256 addr += len;
1257 }
1258 else
1259 {
Daniel Malead01b2952012-11-29 21:49:15 +00001260 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001261 result.SetStatus(eReturnStatusFailed);
1262 return false;
1263 }
1264 }
1265 break;
1266
1267 case eFormatDecimal:
1268 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1269 if (!success)
1270 {
1271 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1272 result.SetStatus(eReturnStatusFailed);
1273 return false;
1274 }
1275 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1276 {
Daniel Malead01b2952012-11-29 21:49:15 +00001277 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001278 result.SetStatus(eReturnStatusFailed);
1279 return false;
1280 }
1281 buffer.PutMaxHex64 (sval64, item_byte_size);
1282 break;
1283
1284 case eFormatUnsigned:
1285 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1286 if (!success)
1287 {
1288 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1289 result.SetStatus(eReturnStatusFailed);
1290 return false;
1291 }
1292 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1293 {
Daniel Malead01b2952012-11-29 21:49:15 +00001294 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001295 result.SetStatus(eReturnStatusFailed);
1296 return false;
1297 }
1298 buffer.PutMaxHex64 (uval64, item_byte_size);
1299 break;
1300
1301 case eFormatOctal:
1302 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1303 if (!success)
1304 {
1305 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1306 result.SetStatus(eReturnStatusFailed);
1307 return false;
1308 }
1309 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1310 {
Daniel Malead01b2952012-11-29 21:49:15 +00001311 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001312 result.SetStatus(eReturnStatusFailed);
1313 return false;
1314 }
1315 buffer.PutMaxHex64 (uval64, item_byte_size);
1316 break;
1317 }
1318 }
1319
1320 if (!buffer.GetString().empty())
1321 {
1322 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001323 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001324 return true;
1325 else
1326 {
Daniel Malead01b2952012-11-29 21:49:15 +00001327 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001328 result.SetStatus(eReturnStatusFailed);
1329 return false;
1330 }
1331 }
1332 return true;
1333 }
1334
Greg Clayton1deb7962011-10-25 06:44:01 +00001335 OptionGroupOptions m_option_group;
1336 OptionGroupFormat m_format_options;
1337 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001338};
1339
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001340
1341//-------------------------------------------------------------------------
1342// CommandObjectMemory
1343//-------------------------------------------------------------------------
1344
Greg Clayton66111032010-06-23 01:19:29 +00001345CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001346 CommandObjectMultiword (interpreter,
1347 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001348 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001349 "memory <subcommand> [<subcommand-options>]")
1350{
Greg Claytona7015092010-09-18 01:14:36 +00001351 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1352 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001353}
1354
1355CommandObjectMemory::~CommandObjectMemory ()
1356{
1357}