blob: 42a8baf46017a4a6f6b300aecc955d277206ebdf [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "CommandObjectMemory.h"
11
12// C Includes
Virgile Bellobdae3782013-08-28 12:14:27 +000013#include <inttypes.h>
14
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015// C++ Includes
16// Other libraries and framework includes
Zachary Turnera78bd7f2015-03-03 23:11:11 +000017#include "clang/AST/Decl.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include "lldb/Core/DataBufferHeap.h"
20#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000021#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000022#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000023#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000024#include "lldb/Core/ValueObjectMemory.h"
Enrico Granata4d93b8c2013-09-30 19:11:51 +000025#include "lldb/DataFormatters/ValueObjectPrinter.h"
Zachary Turneraf0f45f2015-03-03 21:05:17 +000026#include "lldb/Expression/ClangPersistentVariables.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000027#include "lldb/Host/StringConvert.h"
Greg Clayton66111032010-06-23 01:19:29 +000028#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000030#include "lldb/Interpreter/CommandInterpreter.h"
31#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000032#include "lldb/Interpreter/OptionGroupFormat.h"
33#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000034#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000035#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton1f746072012-08-29 21:13:06 +000036#include "lldb/Symbol/TypeList.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000037#include "lldb/Target/MemoryHistory.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038#include "lldb/Target/Process.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000039#include "lldb/Target/StackFrame.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000040#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041
42using namespace lldb;
43using namespace lldb_private;
44
Greg Clayton68ebae62011-04-28 20:55:26 +000045static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000046g_option_table[] =
47{
Zachary Turnerd37221d2014-07-09 16:31:49 +000048 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
49 { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, 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."},
50 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton2346fcf2012-11-02 21:14:58 +000051 { LLDB_OPT_SET_1|
52 LLDB_OPT_SET_2|
Zachary Turnerd37221d2014-07-09 16:31:49 +000053 LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
Greg Clayton84c39662011-04-27 22:04:39 +000054};
55
56
57
58class OptionGroupReadMemory : public OptionGroup
59{
60public:
61
62 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000063 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000064 m_output_as_binary (false),
65 m_view_as_type()
66 {
67 }
68
69 virtual
70 ~OptionGroupReadMemory ()
71 {
72 }
73
74
75 virtual uint32_t
76 GetNumDefinitions ()
77 {
78 return sizeof (g_option_table) / sizeof (OptionDefinition);
79 }
80
81 virtual const OptionDefinition*
82 GetDefinitions ()
83 {
84 return g_option_table;
85 }
86
87 virtual Error
88 SetOptionValue (CommandInterpreter &interpreter,
89 uint32_t option_idx,
90 const char *option_arg)
91 {
92 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000093 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000094
95 switch (short_option)
96 {
97 case 'l':
Pavel Labathc95f7e22015-02-20 11:14:59 +000098 error = m_num_per_line.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +000099 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +0000100 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000101 break;
Greg Clayton1deb7962011-10-25 06:44:01 +0000102
Greg Clayton84c39662011-04-27 22:04:39 +0000103 case 'b':
104 m_output_as_binary = true;
105 break;
106
107 case 't':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000108 error = m_view_as_type.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000109 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000110
111 case 'r':
112 m_force = true;
113 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000114
115 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000116 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000117 break;
118 }
119 return error;
120 }
121
122 virtual void
123 OptionParsingStarting (CommandInterpreter &interpreter)
124 {
Greg Clayton84c39662011-04-27 22:04:39 +0000125 m_num_per_line.Clear();
126 m_output_as_binary = false;
127 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000128 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000129 }
130
Greg Clayton68ebae62011-04-28 20:55:26 +0000131 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000132 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000133 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000134 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000135 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
136 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000137 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000138 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000139 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000140
Greg Clayton68ebae62011-04-28 20:55:26 +0000141 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000142 {
143 default:
144 break;
145
146 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000147 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000148 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000149 if (!num_per_line_option_set)
150 m_num_per_line = 1;
151 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000152 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000153 break;
154
155 case eFormatCString:
156 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000157
158 case eFormatInstruction:
159 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000160 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000161 m_num_per_line = 1;
162 break;
163
164 case eFormatAddressInfo:
165 if (!byte_size_option_set)
166 byte_size_value = target->GetArchitecture().GetAddressByteSize();
167 m_num_per_line = 1;
168 if (!count_option_set)
169 format_options.GetCountValue() = 8;
170 break;
171
Greg Clayton84c39662011-04-27 22:04:39 +0000172 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000173 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000174 if (!num_per_line_option_set)
175 m_num_per_line = 4;
176 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000177 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000178 break;
179
180 case eFormatBinary:
181 case eFormatFloat:
182 case eFormatOctal:
183 case eFormatDecimal:
184 case eFormatEnum:
185 case eFormatUnicode16:
186 case eFormatUnicode32:
187 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000188 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000189 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000190 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000191 if (!num_per_line_option_set)
192 m_num_per_line = 1;
193 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000194 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000195 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000196
Greg Clayton84c39662011-04-27 22:04:39 +0000197 case eFormatBytes:
198 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000199 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000200 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000201 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000202 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000203 "\tconsider using a different display format or don't specify the byte size",
204 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000205 }
206 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000207 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000208 if (!num_per_line_option_set)
209 m_num_per_line = 16;
210 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000211 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000212 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000213 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000214 case eFormatChar:
215 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000216 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000217 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000218 if (!num_per_line_option_set)
219 m_num_per_line = 32;
220 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000221 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000222 break;
223 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000224 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000225 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000226 if (!num_per_line_option_set)
227 m_num_per_line = 1;
228 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000229 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000230 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000231 case eFormatComplexInteger:
232 if (!byte_size_option_set)
233 byte_size_value = 8;
234 if (!num_per_line_option_set)
235 m_num_per_line = 1;
236 if (!count_option_set)
237 format_options.GetCountValue() = 8;
238 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000239 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000240 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000241 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000242 if (!num_per_line_option_set)
243 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000244 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000245 {
246 case 1:
247 case 2:
248 m_num_per_line = 8;
249 break;
250 case 4:
251 m_num_per_line = 4;
252 break;
253 case 8:
254 m_num_per_line = 2;
255 break;
256 default:
257 m_num_per_line = 1;
258 break;
259 }
260 }
261 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000262 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000263 break;
264
265 case eFormatVectorOfChar:
266 case eFormatVectorOfSInt8:
267 case eFormatVectorOfUInt8:
268 case eFormatVectorOfSInt16:
269 case eFormatVectorOfUInt16:
270 case eFormatVectorOfSInt32:
271 case eFormatVectorOfUInt32:
272 case eFormatVectorOfSInt64:
273 case eFormatVectorOfUInt64:
274 case eFormatVectorOfFloat32:
275 case eFormatVectorOfFloat64:
276 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000277 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000278 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000279 if (!num_per_line_option_set)
280 m_num_per_line = 1;
281 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000282 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000283 break;
284 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000285 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000286 }
287
Greg Clayton82f4cf42011-10-26 04:32:38 +0000288 bool
289 AnyOptionWasSet () const
290 {
291 return m_num_per_line.OptionWasSet() ||
292 m_output_as_binary ||
293 m_view_as_type.OptionWasSet();
294 }
295
Greg Clayton84c39662011-04-27 22:04:39 +0000296 OptionValueUInt64 m_num_per_line;
297 bool m_output_as_binary;
298 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000299 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000300};
301
302
303
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000304//----------------------------------------------------------------------
305// Read memory from the inferior process
306//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000307class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000308{
309public:
310
Greg Claytona7015092010-09-18 01:14:36 +0000311 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000312 CommandObjectParsed (interpreter,
313 "memory read",
314 "Read from the memory of the process being debugged.",
315 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +0000316 eCommandRequiresTarget | eCommandProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000317 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000318 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000319 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000320 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000321 m_varobj_options(),
322 m_next_addr(LLDB_INVALID_ADDRESS),
323 m_prev_byte_size(0),
324 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
325 m_prev_memory_options (),
326 m_prev_outfile_options (),
327 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000328 {
Caroline Tice405fe672010-10-04 22:28:36 +0000329 CommandArgumentEntry arg1;
330 CommandArgumentEntry arg2;
331 CommandArgumentData start_addr_arg;
332 CommandArgumentData end_addr_arg;
333
334 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000335 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000336 start_addr_arg.arg_repetition = eArgRepeatPlain;
337
338 // There is only one variant this argument could be; put it into the argument entry.
339 arg1.push_back (start_addr_arg);
340
341 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000342 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000343 end_addr_arg.arg_repetition = eArgRepeatOptional;
344
345 // There is only one variant this argument could be; put it into the argument entry.
346 arg2.push_back (end_addr_arg);
347
348 // Push the data for the first argument into the m_arguments vector.
349 m_arguments.push_back (arg1);
350 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000351
Greg Clayton1deb7962011-10-25 06:44:01 +0000352 // Add the "--format" and "--count" options to group 1 and 3
353 m_option_group.Append (&m_format_options,
354 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000355 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000356 m_option_group.Append (&m_format_options,
357 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000358 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000359 // Add the "--size" option to group 1 and 2
360 m_option_group.Append (&m_format_options,
361 OptionGroupFormat::OPTION_GROUP_SIZE,
362 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000363 m_option_group.Append (&m_memory_options);
364 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 +0000365 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000366 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000367 }
368
369 virtual
370 ~CommandObjectMemoryRead ()
371 {
372 }
373
374 Options *
375 GetOptions ()
376 {
Greg Clayton84c39662011-04-27 22:04:39 +0000377 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000378 }
379
Greg Clayton82f4cf42011-10-26 04:32:38 +0000380 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
381 {
382 return m_cmd_name.c_str();
383 }
384
Jim Ingham5a988412012-06-08 21:56:10 +0000385protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000386 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000387 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388 {
Enrico Granatae87764f2015-05-27 05:04:35 +0000389 // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +0000390 Target *target = m_exe_ctx.GetTargetPtr();
391
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392 const size_t argc = command.GetArgumentCount();
393
Greg Clayton82f4cf42011-10-26 04:32:38 +0000394 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000395 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000396 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 +0000397 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000398 result.SetStatus(eReturnStatusFailed);
399 return false;
400 }
401
Greg Clayton68ebae62011-04-28 20:55:26 +0000402 ClangASTType clang_ast_type;
403 Error error;
404
Greg Clayton84c39662011-04-27 22:04:39 +0000405 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
406 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000407 {
Greg Clayton84c39662011-04-27 22:04:39 +0000408 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000409
Greg Clayton84c39662011-04-27 22:04:39 +0000410 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000411 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000412 TypeList type_list;
413 uint32_t reference_count = 0;
414 uint32_t pointer_count = 0;
415 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000416
417#define ALL_KEYWORDS \
418 KEYWORD("const") \
419 KEYWORD("volatile") \
420 KEYWORD("restrict") \
421 KEYWORD("struct") \
422 KEYWORD("class") \
423 KEYWORD("union")
424
425#define KEYWORD(s) s,
426 static const char *g_keywords[] =
427 {
428 ALL_KEYWORDS
429 };
430#undef KEYWORD
431
432#define KEYWORD(s) (sizeof(s) - 1),
433 static const int g_keyword_lengths[] =
434 {
435 ALL_KEYWORDS
436 };
437#undef KEYWORD
438
439#undef ALL_KEYWORDS
440
441 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000442 std::string type_str(view_as_type_cstr);
443
444 // Remove all instances of g_keywords that are followed by spaces
445 for (size_t i = 0; i < g_num_keywords; ++i)
446 {
447 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000448 int keyword_len = g_keyword_lengths[i];
449
450 idx = 0;
451 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000452 {
453 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000454 {
Greg Clayton84c39662011-04-27 22:04:39 +0000455 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000456 idx = 0;
457 }
458 else
459 {
460 idx += keyword_len;
461 }
Greg Clayton84c39662011-04-27 22:04:39 +0000462 }
463 }
464 bool done = type_str.empty();
465 //
466 idx = type_str.find_first_not_of (" \t");
467 if (idx > 0 && idx != std::string::npos)
468 type_str.erase (0, idx);
469 while (!done)
470 {
471 // Strip trailing spaces
472 if (type_str.empty())
473 done = true;
474 else
475 {
476 switch (type_str[type_str.size()-1])
477 {
478 case '*':
479 ++pointer_count;
480 // fall through...
481 case ' ':
482 case '\t':
483 type_str.erase(type_str.size()-1);
484 break;
485
486 case '&':
487 if (reference_count == 0)
488 {
489 reference_count = 1;
490 type_str.erase(type_str.size()-1);
491 }
492 else
493 {
494 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
495 result.SetStatus(eReturnStatusFailed);
496 return false;
497 }
498 break;
499
500 default:
501 done = true;
502 break;
503 }
504 }
505 }
506
507 ConstString lookup_type_name(type_str.c_str());
Jason Molendab57e4a12013-11-04 09:33:30 +0000508 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000509 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000510 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000511 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000512 if (sc.module_sp)
513 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000514 sc.module_sp->FindTypes (sc,
515 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000516 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000517 1,
518 type_list);
519 }
520 }
521 if (type_list.GetSize() == 0)
522 {
Greg Clayton29399a22012-04-06 17:41:13 +0000523 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000524 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000525 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000526 1,
527 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000528 }
529
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000530 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000531 {
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000532 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
533 if (tdecl)
534 {
Pavel Labathc7c30eb2015-06-08 23:38:06 +0000535 clang_ast_type.SetClangType(&tdecl->getASTContext(),(const lldb::clang_type_t)tdecl->getTypeForDecl());
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000536 }
Greg Clayton84c39662011-04-27 22:04:39 +0000537 }
538
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000539 if (clang_ast_type.IsValid() == false)
540 {
541 if (type_list.GetSize() == 0)
542 {
543 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
544 lookup_type_name.GetCString(),
545 view_as_type_cstr);
546 result.SetStatus(eReturnStatusFailed);
547 return false;
548 }
549 else
550 {
551 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton57ee3062013-07-11 22:46:58 +0000552 clang_ast_type = type_sp->GetClangFullType();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000553 }
554 }
Greg Clayton84c39662011-04-27 22:04:39 +0000555
556 while (pointer_count > 0)
557 {
Greg Clayton57ee3062013-07-11 22:46:58 +0000558 ClangASTType pointer_type = clang_ast_type.GetPointerType();
559 if (pointer_type.IsValid())
560 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000561 else
562 {
563 result.AppendError ("unable make a pointer type\n");
564 result.SetStatus(eReturnStatusFailed);
565 return false;
566 }
567 --pointer_count;
568 }
569
Enrico Granata1cd5e922015-01-28 00:07:51 +0000570 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
Greg Clayton84c39662011-04-27 22:04:39 +0000571
Greg Clayton1deb7962011-10-25 06:44:01 +0000572 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000573 {
574 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
575 view_as_type_cstr);
576 result.SetStatus(eReturnStatusFailed);
577 return false;
578 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000579
Greg Clayton1deb7962011-10-25 06:44:01 +0000580 if (!m_format_options.GetCountValue().OptionWasSet())
581 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000582 }
583 else
584 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000585 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000586 }
587
588 // Look for invalid combinations of settings
589 if (error.Fail())
590 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000591 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000592 result.SetStatus(eReturnStatusFailed);
593 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000594 }
595
Greg Clayton82f4cf42011-10-26 04:32:38 +0000596 lldb::addr_t addr;
597 size_t total_byte_size = 0;
598 if (argc == 0)
599 {
600 // Use the last address and byte size and all options as they were
601 // if no options have been set
602 addr = m_next_addr;
603 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000604 clang_ast_type = m_prev_clang_ast_type;
605 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000606 !m_memory_options.AnyOptionWasSet() &&
607 !m_outfile_options.AnyOptionWasSet() &&
608 !m_varobj_options.AnyOptionWasSet())
609 {
610 m_format_options = m_prev_format_options;
611 m_memory_options = m_prev_memory_options;
612 m_outfile_options = m_prev_outfile_options;
613 m_varobj_options = m_prev_varobj_options;
614 }
615 }
616
Greg Clayton1deb7962011-10-25 06:44:01 +0000617 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000618
619 // TODO For non-8-bit byte addressable architectures this needs to be
620 // revisited to fully support all lldb's range of formatting options.
621 // Furthermore code memory reads (for those architectures) will not
622 // be correctly formatted even w/o formatting options.
623 size_t item_byte_size =
624 target->GetArchitecture().GetDataByteSize() > 1 ?
625 target->GetArchitecture().GetDataByteSize() :
626 m_format_options.GetByteSizeValue().GetCurrentValue();
627
Greg Clayton68ebae62011-04-28 20:55:26 +0000628 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000629
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000630 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000631 {
632 total_byte_size = item_count * item_byte_size;
633 if (total_byte_size == 0)
634 total_byte_size = 32;
635 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000636
Greg Clayton82f4cf42011-10-26 04:32:38 +0000637 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000638 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000639
640 if (addr == LLDB_INVALID_ADDRESS)
641 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000642 result.AppendError("invalid start address expression.");
643 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000644 result.SetStatus(eReturnStatusFailed);
645 return false;
646 }
647
648 if (argc == 2)
649 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000650 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000651 if (end_addr == LLDB_INVALID_ADDRESS)
652 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000653 result.AppendError("invalid end address expression.");
654 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000655 result.SetStatus(eReturnStatusFailed);
656 return false;
657 }
658 else if (end_addr <= addr)
659 {
Daniel Malead01b2952012-11-29 21:49:15 +0000660 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 +0000661 result.SetStatus(eReturnStatusFailed);
662 return false;
663 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000664 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000665 {
Greg Clayton6fea17e2014-03-03 19:15:20 +0000666 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000667 result.SetStatus(eReturnStatusFailed);
668 return false;
669 }
670
671 total_byte_size = end_addr - addr;
672 item_count = total_byte_size / item_byte_size;
673 }
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000674
Enrico Granatad325bf92013-06-04 22:54:16 +0000675 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
676
677 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000678 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000679 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
680 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
681 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 +0000682 return false;
683 }
684
Greg Clayton84c39662011-04-27 22:04:39 +0000685 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000686 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000687 if (clang_ast_type.GetOpaqueQualType())
688 {
689 // Make sure we don't display our type as ASCII bytes like the default memory read
690 if (m_format_options.GetFormatValue().OptionWasSet() == false)
691 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
692
Enrico Granata1cd5e922015-01-28 00:07:51 +0000693 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000694 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000695 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000696 {
Greg Clayton84c39662011-04-27 22:04:39 +0000697 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000698 if (data_sp->GetBytes() == NULL)
699 {
Virgile Belloffeba252014-03-08 17:15:35 +0000700 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size);
Greg Clayton46a44262013-07-24 18:17:35 +0000701 result.SetStatus(eReturnStatusFailed);
702 return false;
703 }
704
Greg Claytone72dfb32012-02-24 01:59:29 +0000705 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000706 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000707 if (bytes_read == 0)
708 {
Greg Clayton57f06302012-05-25 17:05:55 +0000709 const char *error_cstr = error.AsCString();
710 if (error_cstr && error_cstr[0])
711 {
712 result.AppendError(error_cstr);
713 }
714 else
715 {
Daniel Malead01b2952012-11-29 21:49:15 +0000716 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000717 }
Greg Clayton84c39662011-04-27 22:04:39 +0000718 result.SetStatus(eReturnStatusFailed);
719 return false;
720 }
721
722 if (bytes_read < total_byte_size)
Greg Clayton6fea17e2014-03-03 19:15:20 +0000723 result.AppendWarningWithFormat("Not all bytes (%" PRIu64 "/%" PRIu64 ") were able to be read from 0x%" PRIx64 ".\n", (uint64_t)bytes_read, (uint64_t)total_byte_size, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000724 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000725 else
726 {
727 // we treat c-strings as a special case because they do not have a fixed size
728 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
729 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
730 else
731 item_byte_size = target->GetMaximumSizeOfStringSummary();
732 if (!m_format_options.GetCountValue().OptionWasSet())
733 item_count = 1;
734 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000735 if (data_sp->GetBytes() == NULL)
736 {
737 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx64 " bytes for the memory read buffer, specify a smaller size to read", (uint64_t)((item_byte_size+1) * item_count));
738 result.SetStatus(eReturnStatusFailed);
739 return false;
740 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000741 uint8_t *data_ptr = data_sp->GetBytes();
742 auto data_addr = addr;
743 auto count = item_count;
744 item_count = 0;
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000745 bool break_on_no_NULL = false;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000746 while (item_count < count)
747 {
748 std::string buffer;
749 buffer.resize(item_byte_size+1,0);
750 Error error;
751 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
752 if (error.Fail())
753 {
754 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
755 result.SetStatus(eReturnStatusFailed);
756 return false;
757 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000758
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000759 if (item_byte_size == read)
760 {
761 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000762 --read;
763 break_on_no_NULL = true;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000764 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000765 else
766 ++read; // account for final NULL byte
767
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000768 memcpy(data_ptr, &buffer[0], read);
769 data_ptr += read;
770 data_addr += read;
771 bytes_read += read;
772 item_count++; // if we break early we know we only read item_count strings
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000773
774 if (break_on_no_NULL)
775 break;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000776 }
777 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
778 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000779
Greg Clayton2e1f7452012-12-15 02:08:17 +0000780 m_next_addr = addr + bytes_read;
781 m_prev_byte_size = bytes_read;
782 m_prev_format_options = m_format_options;
783 m_prev_memory_options = m_memory_options;
784 m_prev_outfile_options = m_outfile_options;
785 m_prev_varobj_options = m_varobj_options;
786 m_prev_clang_ast_type = clang_ast_type;
787
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000788 StreamFile outfile_stream;
789 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000790 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
791 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000792 {
793 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000794 outfile_spec.GetPath (path, sizeof(path));
795
796 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
797 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
798 if (append)
799 open_options |= File::eOpenOptionAppend;
800
801 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000802 {
Greg Clayton84c39662011-04-27 22:04:39 +0000803 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000804 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000805 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000806 if (bytes_written > 0)
807 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000808 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000809 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000810 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000811 path);
812 return true;
813 }
814 else
815 {
Daniel Malead01b2952012-11-29 21:49:15 +0000816 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000817 result.SetStatus(eReturnStatusFailed);
818 return false;
819 }
820 }
821 else
822 {
823 // We are going to write ASCII to the file just point the
824 // output_stream to our outfile_stream...
825 output_stream = &outfile_stream;
826 }
827 }
828 else
829 {
Greg Clayton84c39662011-04-27 22:04:39 +0000830 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000831 result.SetStatus(eReturnStatusFailed);
832 return false;
833 }
834 }
835 else
836 {
837 output_stream = &result.GetOutputStream();
838 }
839
Greg Clayton84c39662011-04-27 22:04:39 +0000840
Greg Claytonf9fc6092013-01-09 19:44:40 +0000841 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000842 if (clang_ast_type.GetOpaqueQualType())
843 {
844 for (uint32_t i = 0; i<item_count; ++i)
845 {
846 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000847 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000848 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000849 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000850 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000851 name_strm.GetString().c_str(),
852 address,
853 clang_ast_type));
854 if (valobj_sp)
855 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000856 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000857 if (format != eFormatDefault)
858 valobj_sp->SetFormat (format);
859
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000860 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000861
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000862 valobj_sp->Dump(*output_stream,options);
Greg Clayton84c39662011-04-27 22:04:39 +0000863 }
864 else
865 {
866 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
867 view_as_type_cstr,
868 name_strm.GetString().c_str());
869 result.SetStatus(eReturnStatusFailed);
870 return false;
871 }
872 }
873 return true;
874 }
875
876 result.SetStatus(eReturnStatusSuccessFinishResult);
877 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000878 target->GetArchitecture().GetByteOrder(),
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000879 target->GetArchitecture().GetAddressByteSize(),
880 target->GetArchitecture().GetDataByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000881
882 Format format = m_format_options.GetFormat();
883 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
Enrico Granata0947a6e2013-10-29 23:04:29 +0000884 && (item_byte_size != 1))
Enrico Granata31898912013-05-21 17:39:04 +0000885 {
Enrico Granata0947a6e2013-10-29 23:04:29 +0000886 // if a count was not passed, or it is 1
887 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
888 {
889 // this turns requests such as
890 // memory read -fc -s10 -c1 *charPtrPtr
891 // which make no sense (what is a char of size 10?)
892 // into a request for fetching 10 chars of size 1 from the same memory location
893 format = eFormatCharArray;
894 item_count = item_byte_size;
895 item_byte_size = 1;
896 }
897 else
898 {
899 // here we passed a count, and it was not 1
900 // so we have a byte_size and a count
901 // we could well multiply those, but instead let's just fail
Greg Clayton6fea17e2014-03-03 19:15:20 +0000902 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
Enrico Granata0947a6e2013-10-29 23:04:29 +0000903 result.SetStatus(eReturnStatusFailed);
904 return false;
905 }
Enrico Granata31898912013-05-21 17:39:04 +0000906 }
Greg Clayton84c39662011-04-27 22:04:39 +0000907
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000908 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000909 size_t bytes_dumped = data.Dump (output_stream,
910 0,
Enrico Granata31898912013-05-21 17:39:04 +0000911 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000912 item_byte_size,
913 item_count,
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000914 num_per_line / target->GetArchitecture().GetDataByteSize(),
Greg Claytonc7bece562013-01-25 18:06:21 +0000915 addr,
916 0,
917 0,
918 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000919 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000920 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000921 return true;
922 }
923
Greg Clayton84c39662011-04-27 22:04:39 +0000924 OptionGroupOptions m_option_group;
925 OptionGroupFormat m_format_options;
926 OptionGroupReadMemory m_memory_options;
927 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000928 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000929 lldb::addr_t m_next_addr;
930 lldb::addr_t m_prev_byte_size;
931 OptionGroupFormat m_prev_format_options;
932 OptionGroupReadMemory m_prev_memory_options;
933 OptionGroupOutputFile m_prev_outfile_options;
934 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000935 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000936};
937
Enrico Granata53468432013-11-13 02:18:44 +0000938OptionDefinition
939g_memory_find_option_table[] =
940{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000941 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
942 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
943 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."},
944 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
Enrico Granata53468432013-11-13 02:18:44 +0000945};
946
Enrico Granata53468432013-11-13 02:18:44 +0000947//----------------------------------------------------------------------
948// Find the specified data in memory
949//----------------------------------------------------------------------
950class CommandObjectMemoryFind : public CommandObjectParsed
951{
952public:
953
954 class OptionGroupFindMemory : public OptionGroup
955 {
956 public:
957 OptionGroupFindMemory () :
958 OptionGroup(),
959 m_count(1),
Enrico Granata8d81a842013-11-13 20:08:30 +0000960 m_offset(0)
Enrico Granata53468432013-11-13 02:18:44 +0000961 {
962 }
963
964 virtual
965 ~OptionGroupFindMemory ()
966 {
967 }
968
969 virtual uint32_t
970 GetNumDefinitions ()
971 {
972 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
973 }
974
975 virtual const OptionDefinition*
976 GetDefinitions ()
977 {
978 return g_memory_find_option_table;
979 }
980
981 virtual Error
982 SetOptionValue (CommandInterpreter &interpreter,
983 uint32_t option_idx,
984 const char *option_arg)
985 {
986 Error error;
987 const int short_option = g_memory_find_option_table[option_idx].short_option;
988
989 switch (short_option)
990 {
991 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000992 m_expr.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +0000993 break;
994
995 case 's':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000996 m_string.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +0000997 break;
998
999 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001000 if (m_count.SetValueFromString(option_arg).Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001001 error.SetErrorString("unrecognized value for count");
1002 break;
1003
Enrico Granata8d81a842013-11-13 20:08:30 +00001004 case 'o':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001005 if (m_offset.SetValueFromString(option_arg).Fail())
Enrico Granata8d81a842013-11-13 20:08:30 +00001006 error.SetErrorString("unrecognized value for dump-offset");
1007 break;
1008
Enrico Granata53468432013-11-13 02:18:44 +00001009 default:
1010 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1011 break;
1012 }
1013 return error;
1014 }
1015
1016 virtual void
1017 OptionParsingStarting (CommandInterpreter &interpreter)
1018 {
1019 m_expr.Clear();
1020 m_string.Clear();
1021 m_count.Clear();
Enrico Granata53468432013-11-13 02:18:44 +00001022 }
1023
1024 OptionValueString m_expr;
1025 OptionValueString m_string;
1026 OptionValueUInt64 m_count;
Enrico Granata8d81a842013-11-13 20:08:30 +00001027 OptionValueUInt64 m_offset;
Enrico Granata53468432013-11-13 02:18:44 +00001028 };
1029
1030 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1031 CommandObjectParsed (interpreter,
1032 "memory find",
1033 "Find a value in the memory of the process being debugged.",
1034 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001035 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Enrico Granata53468432013-11-13 02:18:44 +00001036 m_option_group (interpreter),
1037 m_memory_options ()
1038 {
1039 CommandArgumentEntry arg1;
1040 CommandArgumentEntry arg2;
1041 CommandArgumentData addr_arg;
1042 CommandArgumentData value_arg;
1043
1044 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001045 addr_arg.arg_type = eArgTypeAddressOrExpression;
Enrico Granata53468432013-11-13 02:18:44 +00001046 addr_arg.arg_repetition = eArgRepeatPlain;
1047
1048 // There is only one variant this argument could be; put it into the argument entry.
1049 arg1.push_back (addr_arg);
1050
1051 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001052 value_arg.arg_type = eArgTypeAddressOrExpression;
1053 value_arg.arg_repetition = eArgRepeatPlain;
Enrico Granata53468432013-11-13 02:18:44 +00001054
1055 // There is only one variant this argument could be; put it into the argument entry.
1056 arg2.push_back (value_arg);
1057
1058 // Push the data for the first argument into the m_arguments vector.
1059 m_arguments.push_back (arg1);
1060 m_arguments.push_back (arg2);
1061
1062 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1063 m_option_group.Finalize();
1064 }
1065
1066 virtual
1067 ~CommandObjectMemoryFind ()
1068 {
1069 }
1070
1071 Options *
1072 GetOptions ()
1073 {
1074 return &m_option_group;
1075 }
1076
1077protected:
1078 virtual bool
1079 DoExecute (Args& command, CommandReturnObject &result)
1080 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001081 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Enrico Granata53468432013-11-13 02:18:44 +00001082 Process *process = m_exe_ctx.GetProcessPtr();
1083
1084 const size_t argc = command.GetArgumentCount();
1085
1086 if (argc != 2)
1087 {
Enrico Granata6e49c482013-11-13 02:22:24 +00001088 result.AppendError("two addresses needed for memory find");
Enrico Granata53468432013-11-13 02:18:44 +00001089 return false;
1090 }
1091
1092 Error error;
1093 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1094 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1095 {
1096 result.AppendError("invalid low address");
1097 return false;
1098 }
1099 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1100 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1101 {
Ed Maste47a8a5e2014-09-06 11:29:08 +00001102 result.AppendError("invalid high address");
Enrico Granata53468432013-11-13 02:18:44 +00001103 return false;
1104 }
1105
1106 if (high_addr <= low_addr)
1107 {
1108 result.AppendError("starting address must be smaller than ending address");
1109 return false;
1110 }
1111
1112 lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1113
1114 DataBufferHeap buffer;
1115
1116 if (m_memory_options.m_string.OptionWasSet())
1117 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1118 else if (m_memory_options.m_expr.OptionWasSet())
1119 {
1120 StackFrame* frame = m_exe_ctx.GetFramePtr();
1121 ValueObjectSP result_sp;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001122 if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
1123 result_sp.get())
Enrico Granata53468432013-11-13 02:18:44 +00001124 {
1125 uint64_t value = result_sp->GetValueAsUnsigned(0);
Enrico Granata1cd5e922015-01-28 00:07:51 +00001126 switch (result_sp->GetClangType().GetByteSize(nullptr))
Enrico Granata53468432013-11-13 02:18:44 +00001127 {
1128 case 1: {
1129 uint8_t byte = (uint8_t)value;
1130 buffer.CopyData(&byte,1);
1131 }
1132 break;
1133 case 2: {
1134 uint16_t word = (uint16_t)value;
1135 buffer.CopyData(&word,2);
1136 }
1137 break;
1138 case 4: {
1139 uint32_t lword = (uint32_t)value;
1140 buffer.CopyData(&lword,4);
1141 }
1142 break;
1143 case 8: {
1144 buffer.CopyData(&value, 8);
1145 }
1146 break;
1147 case 3:
1148 case 5:
1149 case 6:
1150 case 7:
1151 result.AppendError("unknown type. pass a string instead");
1152 return false;
1153 default:
Enrico Granata0b3b9872015-08-03 18:51:39 +00001154 result.AppendError("result size larger than 8 bytes. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001155 return false;
1156 }
1157 }
1158 else
1159 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001160 result.AppendError("expression evaluation failed. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001161 return false;
1162 }
1163 }
1164 else
1165 {
1166 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1167 return false;
1168 }
1169
1170 size_t count = m_memory_options.m_count.GetCurrentValue();
1171 found_location = low_addr;
1172 bool ever_found = false;
1173 while (count)
1174 {
1175 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1176 if (found_location == LLDB_INVALID_ADDRESS)
1177 {
1178 if (!ever_found)
1179 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001180 result.AppendMessage("data not found within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001181 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1182 }
1183 else
Enrico Granata0b3b9872015-08-03 18:51:39 +00001184 result.AppendMessage("no more matches within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001185 break;
1186 }
Enrico Granata0b3b9872015-08-03 18:51:39 +00001187 result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location);
Enrico Granata8d81a842013-11-13 20:08:30 +00001188
1189 DataBufferHeap dumpbuffer(32,0);
1190 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1191 if (!error.Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001192 {
Enrico Granata8d81a842013-11-13 20:08:30 +00001193 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1194 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1195 result.GetOutputStream().EOL();
Enrico Granata53468432013-11-13 02:18:44 +00001196 }
Enrico Granata8d81a842013-11-13 20:08:30 +00001197
Enrico Granata53468432013-11-13 02:18:44 +00001198 --count;
1199 found_location++;
1200 ever_found = true;
1201 }
1202
1203 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1204 return true;
1205 }
1206
1207 lldb::addr_t
1208 Search (lldb::addr_t low,
1209 lldb::addr_t high,
1210 uint8_t* buffer,
1211 size_t buffer_size)
1212 {
1213 Process *process = m_exe_ctx.GetProcessPtr();
1214 DataBufferHeap heap(buffer_size, 0);
Enrico Granata53468432013-11-13 02:18:44 +00001215 for (auto ptr = low;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001216 ptr < high;
1217 ptr++)
Enrico Granata53468432013-11-13 02:18:44 +00001218 {
1219 Error error;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001220 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
Enrico Granata53468432013-11-13 02:18:44 +00001221 if (error.Fail())
1222 return LLDB_INVALID_ADDRESS;
1223 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
Enrico Granata0b3b9872015-08-03 18:51:39 +00001224 return ptr;
Enrico Granata53468432013-11-13 02:18:44 +00001225 }
1226 return LLDB_INVALID_ADDRESS;
1227 }
1228
1229 OptionGroupOptions m_option_group;
1230 OptionGroupFindMemory m_memory_options;
1231};
1232
Greg Clayton1deb7962011-10-25 06:44:01 +00001233
1234OptionDefinition
1235g_memory_write_option_table[] =
1236{
Zachary Turnerd37221d2014-07-09 16:31:49 +00001237{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
Bruce Mitchener350b78e2014-07-10 14:45:57 +00001238{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."},
Greg Clayton1deb7962011-10-25 06:44:01 +00001239};
1240
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001241//----------------------------------------------------------------------
1242// Write memory to the inferior process
1243//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001244class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001245{
1246public:
1247
Greg Clayton1deb7962011-10-25 06:44:01 +00001248 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001249 {
1250 public:
Greg Clayton1deb7962011-10-25 06:44:01 +00001251 OptionGroupWriteMemory () :
1252 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001253 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001254 }
1255
1256 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +00001257 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001258 {
1259 }
1260
Greg Clayton1deb7962011-10-25 06:44:01 +00001261 virtual uint32_t
1262 GetNumDefinitions ()
1263 {
1264 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1265 }
Enrico Granata53468432013-11-13 02:18:44 +00001266
Greg Clayton1deb7962011-10-25 06:44:01 +00001267 virtual const OptionDefinition*
1268 GetDefinitions ()
1269 {
1270 return g_memory_write_option_table;
1271 }
Enrico Granata53468432013-11-13 02:18:44 +00001272
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001273 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +00001274 SetOptionValue (CommandInterpreter &interpreter,
1275 uint32_t option_idx,
1276 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001277 {
1278 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001279 const int short_option = g_memory_write_option_table[option_idx].short_option;
Enrico Granata53468432013-11-13 02:18:44 +00001280
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001281 switch (short_option)
1282 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001283 case 'i':
1284 m_infile.SetFile (option_arg, true);
1285 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001286 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001287 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +00001288 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001289 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001290 break;
Enrico Granata53468432013-11-13 02:18:44 +00001291
Greg Clayton1deb7962011-10-25 06:44:01 +00001292 case 'o':
1293 {
1294 bool success;
Vince Harron5275aaa2015-01-15 20:08:35 +00001295 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
Greg Clayton1deb7962011-10-25 06:44:01 +00001296 if (!success)
1297 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001298 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +00001299 }
1300 }
1301 break;
1302
1303 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001304 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +00001305 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001306 }
1307 return error;
1308 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001309
1310 virtual void
1311 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001312 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001313 m_infile.Clear();
1314 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001315 }
1316
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001317 FileSpec m_infile;
1318 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001319 };
1320
Greg Claytona7015092010-09-18 01:14:36 +00001321 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001322 CommandObjectParsed (interpreter,
1323 "memory write",
1324 "Write to the memory of the process being debugged.",
1325 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001326 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001327 m_option_group (interpreter),
1328 m_format_options (eFormatBytes, 1, UINT64_MAX),
1329 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001330 {
Caroline Tice405fe672010-10-04 22:28:36 +00001331 CommandArgumentEntry arg1;
1332 CommandArgumentEntry arg2;
1333 CommandArgumentData addr_arg;
1334 CommandArgumentData value_arg;
1335
1336 // Define the first (and only) variant of this arg.
1337 addr_arg.arg_type = eArgTypeAddress;
1338 addr_arg.arg_repetition = eArgRepeatPlain;
1339
1340 // There is only one variant this argument could be; put it into the argument entry.
1341 arg1.push_back (addr_arg);
1342
1343 // Define the first (and only) variant of this arg.
1344 value_arg.arg_type = eArgTypeValue;
1345 value_arg.arg_repetition = eArgRepeatPlus;
1346
1347 // There is only one variant this argument could be; put it into the argument entry.
1348 arg2.push_back (value_arg);
1349
1350 // Push the data for the first argument into the m_arguments vector.
1351 m_arguments.push_back (arg1);
1352 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001353
1354 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1355 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1356 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1357 m_option_group.Finalize();
1358
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001359 }
1360
1361 virtual
1362 ~CommandObjectMemoryWrite ()
1363 {
1364 }
1365
1366 Options *
1367 GetOptions ()
1368 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001369 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001370 }
1371
1372 bool
1373 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1374 {
1375 if (total_byte_size > 8)
1376 return false;
1377
1378 if (total_byte_size == 8)
1379 return true;
1380
1381 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1382 return uval64 <= max;
1383 }
1384
1385 bool
1386 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1387 {
1388 if (total_byte_size > 8)
1389 return false;
1390
1391 if (total_byte_size == 8)
1392 return true;
1393
1394 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1395 const int64_t min = ~(max);
1396 return min <= sval64 && sval64 <= max;
1397 }
1398
Jim Ingham5a988412012-06-08 21:56:10 +00001399protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001400 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001401 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001402 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001403 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +00001404 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001405
1406 const size_t argc = command.GetArgumentCount();
1407
Greg Clayton1deb7962011-10-25 06:44:01 +00001408 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001409 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001410 if (argc < 1)
1411 {
1412 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1413 result.SetStatus(eReturnStatusFailed);
1414 return false;
1415 }
1416 }
1417 else if (argc < 2)
1418 {
1419 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 +00001420 result.SetStatus(eReturnStatusFailed);
1421 return false;
1422 }
1423
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001424 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001425 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1426 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001427
Greg Clayton1deb7962011-10-25 06:44:01 +00001428 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1429 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001430
Greg Claytonb9d5df52012-12-06 22:49:16 +00001431 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001432 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001433 command.GetArgumentAtIndex(0),
1434 LLDB_INVALID_ADDRESS,
1435 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001436
1437 if (addr == LLDB_INVALID_ADDRESS)
1438 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001439 result.AppendError("invalid address expression\n");
1440 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001441 result.SetStatus(eReturnStatusFailed);
1442 return false;
1443 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001444
Greg Clayton1deb7962011-10-25 06:44:01 +00001445 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001446 {
1447 size_t length = SIZE_MAX;
Jason Molenda250b1b892015-02-03 23:39:47 +00001448 if (item_byte_size > 1)
Greg Clayton1deb7962011-10-25 06:44:01 +00001449 length = item_byte_size;
1450 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001451 if (data_sp)
1452 {
1453 length = data_sp->GetByteSize();
1454 if (length > 0)
1455 {
1456 Error error;
1457 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1458
1459 if (bytes_written == length)
1460 {
1461 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001462 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001463 result.SetStatus(eReturnStatusSuccessFinishResult);
1464 }
1465 else if (bytes_written > 0)
1466 {
1467 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001468 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 +00001469 result.SetStatus(eReturnStatusSuccessFinishResult);
1470 }
1471 else
1472 {
Daniel Malead01b2952012-11-29 21:49:15 +00001473 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001474 result.SetStatus(eReturnStatusFailed);
1475 }
1476 }
1477 }
1478 else
1479 {
1480 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1481 result.SetStatus(eReturnStatusFailed);
1482 }
1483 return result.Succeeded();
1484 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001485 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001486 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001487 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001488 item_byte_size = buffer.GetAddressByteSize();
1489 else
1490 item_byte_size = 1;
1491 }
1492
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001493 command.Shift(); // shift off the address argument
1494 uint64_t uval64;
1495 int64_t sval64;
1496 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001497 const size_t num_value_args = command.GetArgumentCount();
1498 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001499 {
1500 const char *value_str = command.GetArgumentAtIndex(i);
1501
Greg Clayton1deb7962011-10-25 06:44:01 +00001502 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001503 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001504 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001505 case eFormatFloat: // TODO: add support for floats soon
1506 case eFormatCharPrintable:
1507 case eFormatBytesWithASCII:
1508 case eFormatComplex:
1509 case eFormatEnum:
1510 case eFormatUnicode16:
1511 case eFormatUnicode32:
1512 case eFormatVectorOfChar:
1513 case eFormatVectorOfSInt8:
1514 case eFormatVectorOfUInt8:
1515 case eFormatVectorOfSInt16:
1516 case eFormatVectorOfUInt16:
1517 case eFormatVectorOfSInt32:
1518 case eFormatVectorOfUInt32:
1519 case eFormatVectorOfSInt64:
1520 case eFormatVectorOfUInt64:
1521 case eFormatVectorOfFloat32:
1522 case eFormatVectorOfFloat64:
1523 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001524 case eFormatOSType:
1525 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001526 case eFormatAddressInfo:
1527 case eFormatHexFloat:
1528 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001529 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001530 result.AppendError("unsupported format for writing memory");
1531 result.SetStatus(eReturnStatusFailed);
1532 return false;
1533
1534 case eFormatDefault:
1535 case eFormatBytes:
1536 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001537 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001538 case eFormatPointer:
1539
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001540 // Decode hex bytes
Vince Harron5275aaa2015-01-15 20:08:35 +00001541 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001542 if (!success)
1543 {
1544 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1545 result.SetStatus(eReturnStatusFailed);
1546 return false;
1547 }
1548 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1549 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001550 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001551 result.SetStatus(eReturnStatusFailed);
1552 return false;
1553 }
1554 buffer.PutMaxHex64 (uval64, item_byte_size);
1555 break;
1556
1557 case eFormatBoolean:
1558 uval64 = Args::StringToBoolean(value_str, false, &success);
1559 if (!success)
1560 {
1561 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1562 result.SetStatus(eReturnStatusFailed);
1563 return false;
1564 }
1565 buffer.PutMaxHex64 (uval64, item_byte_size);
1566 break;
1567
1568 case eFormatBinary:
Vince Harron5275aaa2015-01-15 20:08:35 +00001569 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001570 if (!success)
1571 {
1572 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1573 result.SetStatus(eReturnStatusFailed);
1574 return false;
1575 }
1576 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1577 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001578 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001579 result.SetStatus(eReturnStatusFailed);
1580 return false;
1581 }
1582 buffer.PutMaxHex64 (uval64, item_byte_size);
1583 break;
1584
Greg Clayton4e4294b2011-06-17 23:50:44 +00001585 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001586 case eFormatChar:
1587 case eFormatCString:
1588 if (value_str[0])
1589 {
1590 size_t len = strlen (value_str);
1591 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001592 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001593 ++len;
1594 Error error;
1595 if (process->WriteMemory (addr, value_str, len, error) == len)
1596 {
1597 addr += len;
1598 }
1599 else
1600 {
Daniel Malead01b2952012-11-29 21:49:15 +00001601 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001602 result.SetStatus(eReturnStatusFailed);
1603 return false;
1604 }
1605 }
1606 break;
1607
1608 case eFormatDecimal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001609 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001610 if (!success)
1611 {
1612 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1613 result.SetStatus(eReturnStatusFailed);
1614 return false;
1615 }
1616 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1617 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001618 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %" PRIu64 " byte signed integer value.\n", sval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001619 result.SetStatus(eReturnStatusFailed);
1620 return false;
1621 }
1622 buffer.PutMaxHex64 (sval64, item_byte_size);
1623 break;
1624
1625 case eFormatUnsigned:
Vince Harron5275aaa2015-01-15 20:08:35 +00001626 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001627 if (!success)
1628 {
1629 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1630 result.SetStatus(eReturnStatusFailed);
1631 return false;
1632 }
1633 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1634 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001635 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001636 result.SetStatus(eReturnStatusFailed);
1637 return false;
1638 }
1639 buffer.PutMaxHex64 (uval64, item_byte_size);
1640 break;
1641
1642 case eFormatOctal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001643 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001644 if (!success)
1645 {
1646 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1647 result.SetStatus(eReturnStatusFailed);
1648 return false;
1649 }
1650 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1651 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001652 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001653 result.SetStatus(eReturnStatusFailed);
1654 return false;
1655 }
1656 buffer.PutMaxHex64 (uval64, item_byte_size);
1657 break;
1658 }
1659 }
1660
1661 if (!buffer.GetString().empty())
1662 {
1663 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001664 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001665 return true;
1666 else
1667 {
Daniel Malead01b2952012-11-29 21:49:15 +00001668 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001669 result.SetStatus(eReturnStatusFailed);
1670 return false;
1671 }
1672 }
1673 return true;
1674 }
1675
Greg Clayton1deb7962011-10-25 06:44:01 +00001676 OptionGroupOptions m_option_group;
1677 OptionGroupFormat m_format_options;
1678 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001679};
1680
Kuba Breckabeed8212014-09-04 01:03:18 +00001681//----------------------------------------------------------------------
1682// Get malloc/free history of a memory address.
1683//----------------------------------------------------------------------
1684class CommandObjectMemoryHistory : public CommandObjectParsed
1685{
1686public:
1687
1688 CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1689 CommandObjectParsed (interpreter,
1690 "memory history",
1691 "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1692 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001693 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | eCommandProcessMustBeLaunched)
Kuba Breckabeed8212014-09-04 01:03:18 +00001694 {
1695 CommandArgumentEntry arg1;
1696 CommandArgumentData addr_arg;
1697
1698 // Define the first (and only) variant of this arg.
1699 addr_arg.arg_type = eArgTypeAddress;
1700 addr_arg.arg_repetition = eArgRepeatPlain;
1701
1702 // There is only one variant this argument could be; put it into the argument entry.
1703 arg1.push_back (addr_arg);
1704
1705 // Push the data for the first argument into the m_arguments vector.
1706 m_arguments.push_back (arg1);
1707 }
1708
1709 virtual
1710 ~CommandObjectMemoryHistory ()
1711 {
1712 }
1713
1714 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
1715 {
1716 return m_cmd_name.c_str();
1717 }
1718
1719protected:
1720 virtual bool
1721 DoExecute (Args& command, CommandReturnObject &result)
1722 {
1723 const size_t argc = command.GetArgumentCount();
1724
1725 if (argc == 0 || argc > 1)
1726 {
1727 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1728 result.SetStatus(eReturnStatusFailed);
1729 return false;
1730 }
1731
1732 Error error;
1733 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1734 command.GetArgumentAtIndex(0),
1735 LLDB_INVALID_ADDRESS,
1736 &error);
1737
1738 if (addr == LLDB_INVALID_ADDRESS)
1739 {
1740 result.AppendError("invalid address expression");
1741 result.AppendError(error.AsCString());
1742 result.SetStatus(eReturnStatusFailed);
1743 return false;
1744 }
1745
1746 Stream *output_stream = &result.GetOutputStream();
1747
1748 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1749 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1750
1751 if (! memory_history.get())
1752 {
1753 result.AppendError("no available memory history provider");
1754 result.SetStatus(eReturnStatusFailed);
1755 return false;
1756 }
1757
1758 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1759
1760 for (auto thread : thread_list) {
1761 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1762 }
1763
1764 result.SetStatus(eReturnStatusSuccessFinishResult);
1765
1766 return true;
1767 }
1768
1769};
1770
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001771
1772//-------------------------------------------------------------------------
1773// CommandObjectMemory
1774//-------------------------------------------------------------------------
1775
Greg Clayton66111032010-06-23 01:19:29 +00001776CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001777 CommandObjectMultiword (interpreter,
1778 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001779 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001780 "memory <subcommand> [<subcommand-options>]")
1781{
Enrico Granata53468432013-11-13 02:18:44 +00001782 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001783 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1784 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Kuba Breckabeed8212014-09-04 01:03:18 +00001785 LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001786}
1787
1788CommandObjectMemory::~CommandObjectMemory ()
1789{
1790}