blob: 9eca2a8bb13a8f882e4831adb6a452e058d49452 [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 Claytond8d4a572015-08-11 21:38:15 +000036#include "lldb/Symbol/ClangASTContext.h"
Greg Clayton1f746072012-08-29 21:13:06 +000037#include "lldb/Symbol/TypeList.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000038#include "lldb/Target/MemoryHistory.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000039#include "lldb/Target/Process.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000040#include "lldb/Target/StackFrame.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000041#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042
43using namespace lldb;
44using namespace lldb_private;
45
Greg Clayton68ebae62011-04-28 20:55:26 +000046static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000047g_option_table[] =
48{
Zachary Turnerd37221d2014-07-09 16:31:49 +000049 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
50 { 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."},
51 { 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 +000052 { LLDB_OPT_SET_1|
53 LLDB_OPT_SET_2|
Zachary Turnerd37221d2014-07-09 16:31:49 +000054 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 +000055};
56
57
58
59class OptionGroupReadMemory : public OptionGroup
60{
61public:
62
63 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000064 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000065 m_output_as_binary (false),
66 m_view_as_type()
67 {
68 }
69
70 virtual
71 ~OptionGroupReadMemory ()
72 {
73 }
74
75
76 virtual uint32_t
77 GetNumDefinitions ()
78 {
79 return sizeof (g_option_table) / sizeof (OptionDefinition);
80 }
81
82 virtual const OptionDefinition*
83 GetDefinitions ()
84 {
85 return g_option_table;
86 }
87
88 virtual Error
89 SetOptionValue (CommandInterpreter &interpreter,
90 uint32_t option_idx,
91 const char *option_arg)
92 {
93 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000094 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000095
96 switch (short_option)
97 {
98 case 'l':
Pavel Labathc95f7e22015-02-20 11:14:59 +000099 error = m_num_per_line.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000100 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +0000101 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000102 break;
Greg Clayton1deb7962011-10-25 06:44:01 +0000103
Greg Clayton84c39662011-04-27 22:04:39 +0000104 case 'b':
105 m_output_as_binary = true;
106 break;
107
108 case 't':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000109 error = m_view_as_type.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000110 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000111
112 case 'r':
113 m_force = true;
114 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000115
116 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000117 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000118 break;
119 }
120 return error;
121 }
122
123 virtual void
124 OptionParsingStarting (CommandInterpreter &interpreter)
125 {
Greg Clayton84c39662011-04-27 22:04:39 +0000126 m_num_per_line.Clear();
127 m_output_as_binary = false;
128 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000129 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000130 }
131
Greg Clayton68ebae62011-04-28 20:55:26 +0000132 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000133 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000134 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000135 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000136 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
137 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000138 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000139 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000140 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000141
Greg Clayton68ebae62011-04-28 20:55:26 +0000142 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000143 {
144 default:
145 break;
146
147 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000148 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000149 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000150 if (!num_per_line_option_set)
151 m_num_per_line = 1;
152 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000153 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000154 break;
155
156 case eFormatCString:
157 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000158
159 case eFormatInstruction:
160 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000161 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000162 m_num_per_line = 1;
163 break;
164
165 case eFormatAddressInfo:
166 if (!byte_size_option_set)
167 byte_size_value = target->GetArchitecture().GetAddressByteSize();
168 m_num_per_line = 1;
169 if (!count_option_set)
170 format_options.GetCountValue() = 8;
171 break;
172
Greg Clayton84c39662011-04-27 22:04:39 +0000173 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000174 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000175 if (!num_per_line_option_set)
176 m_num_per_line = 4;
177 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000178 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000179 break;
180
181 case eFormatBinary:
182 case eFormatFloat:
183 case eFormatOctal:
184 case eFormatDecimal:
185 case eFormatEnum:
186 case eFormatUnicode16:
187 case eFormatUnicode32:
188 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000189 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000190 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000191 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000192 if (!num_per_line_option_set)
193 m_num_per_line = 1;
194 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000195 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000196 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000197
Greg Clayton84c39662011-04-27 22:04:39 +0000198 case eFormatBytes:
199 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000200 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000201 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000202 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000203 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000204 "\tconsider using a different display format or don't specify the byte size",
205 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000206 }
207 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000208 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000209 if (!num_per_line_option_set)
210 m_num_per_line = 16;
211 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000212 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000213 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000214 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000215 case eFormatChar:
216 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000217 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000218 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000219 if (!num_per_line_option_set)
220 m_num_per_line = 32;
221 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000222 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000223 break;
224 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000225 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000226 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000227 if (!num_per_line_option_set)
228 m_num_per_line = 1;
229 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000230 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000231 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000232 case eFormatComplexInteger:
233 if (!byte_size_option_set)
234 byte_size_value = 8;
235 if (!num_per_line_option_set)
236 m_num_per_line = 1;
237 if (!count_option_set)
238 format_options.GetCountValue() = 8;
239 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000240 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000241 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000242 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000243 if (!num_per_line_option_set)
244 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000245 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000246 {
247 case 1:
248 case 2:
249 m_num_per_line = 8;
250 break;
251 case 4:
252 m_num_per_line = 4;
253 break;
254 case 8:
255 m_num_per_line = 2;
256 break;
257 default:
258 m_num_per_line = 1;
259 break;
260 }
261 }
262 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000263 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000264 break;
265
266 case eFormatVectorOfChar:
267 case eFormatVectorOfSInt8:
268 case eFormatVectorOfUInt8:
269 case eFormatVectorOfSInt16:
270 case eFormatVectorOfUInt16:
271 case eFormatVectorOfSInt32:
272 case eFormatVectorOfUInt32:
273 case eFormatVectorOfSInt64:
274 case eFormatVectorOfUInt64:
275 case eFormatVectorOfFloat32:
276 case eFormatVectorOfFloat64:
277 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000278 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000279 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000280 if (!num_per_line_option_set)
281 m_num_per_line = 1;
282 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000283 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000284 break;
285 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000286 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000287 }
288
Greg Clayton82f4cf42011-10-26 04:32:38 +0000289 bool
290 AnyOptionWasSet () const
291 {
292 return m_num_per_line.OptionWasSet() ||
293 m_output_as_binary ||
294 m_view_as_type.OptionWasSet();
295 }
296
Greg Clayton84c39662011-04-27 22:04:39 +0000297 OptionValueUInt64 m_num_per_line;
298 bool m_output_as_binary;
299 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000300 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000301};
302
303
304
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305//----------------------------------------------------------------------
306// Read memory from the inferior process
307//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000308class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000309{
310public:
311
Greg Claytona7015092010-09-18 01:14:36 +0000312 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000313 CommandObjectParsed (interpreter,
314 "memory read",
315 "Read from the memory of the process being debugged.",
316 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +0000317 eCommandRequiresTarget | eCommandProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000318 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000319 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000320 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000321 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000322 m_varobj_options(),
323 m_next_addr(LLDB_INVALID_ADDRESS),
324 m_prev_byte_size(0),
325 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
326 m_prev_memory_options (),
327 m_prev_outfile_options (),
328 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000329 {
Caroline Tice405fe672010-10-04 22:28:36 +0000330 CommandArgumentEntry arg1;
331 CommandArgumentEntry arg2;
332 CommandArgumentData start_addr_arg;
333 CommandArgumentData end_addr_arg;
334
335 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000336 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000337 start_addr_arg.arg_repetition = eArgRepeatPlain;
338
339 // There is only one variant this argument could be; put it into the argument entry.
340 arg1.push_back (start_addr_arg);
341
342 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000343 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000344 end_addr_arg.arg_repetition = eArgRepeatOptional;
345
346 // There is only one variant this argument could be; put it into the argument entry.
347 arg2.push_back (end_addr_arg);
348
349 // Push the data for the first argument into the m_arguments vector.
350 m_arguments.push_back (arg1);
351 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000352
Greg Clayton1deb7962011-10-25 06:44:01 +0000353 // Add the "--format" and "--count" options to group 1 and 3
354 m_option_group.Append (&m_format_options,
355 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000356 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000357 m_option_group.Append (&m_format_options,
358 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000359 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000360 // Add the "--size" option to group 1 and 2
361 m_option_group.Append (&m_format_options,
362 OptionGroupFormat::OPTION_GROUP_SIZE,
363 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000364 m_option_group.Append (&m_memory_options);
365 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 +0000366 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000367 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000368 }
369
370 virtual
371 ~CommandObjectMemoryRead ()
372 {
373 }
374
375 Options *
376 GetOptions ()
377 {
Greg Clayton84c39662011-04-27 22:04:39 +0000378 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000379 }
380
Greg Clayton82f4cf42011-10-26 04:32:38 +0000381 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
382 {
383 return m_cmd_name.c_str();
384 }
385
Jim Ingham5a988412012-06-08 21:56:10 +0000386protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000388 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000389 {
Enrico Granatae87764f2015-05-27 05:04:35 +0000390 // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +0000391 Target *target = m_exe_ctx.GetTargetPtr();
392
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393 const size_t argc = command.GetArgumentCount();
394
Greg Clayton82f4cf42011-10-26 04:32:38 +0000395 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000396 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000397 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 +0000398 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000399 result.SetStatus(eReturnStatusFailed);
400 return false;
401 }
402
Greg Claytona1e5dc82015-08-11 22:53:00 +0000403 CompilerType clang_ast_type;
Greg Clayton68ebae62011-04-28 20:55:26 +0000404 Error error;
405
Greg Clayton84c39662011-04-27 22:04:39 +0000406 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
407 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000408 {
Greg Clayton84c39662011-04-27 22:04:39 +0000409 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000410
Greg Clayton84c39662011-04-27 22:04:39 +0000411 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000412 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000413 TypeList type_list;
414 uint32_t reference_count = 0;
415 uint32_t pointer_count = 0;
416 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000417
418#define ALL_KEYWORDS \
419 KEYWORD("const") \
420 KEYWORD("volatile") \
421 KEYWORD("restrict") \
422 KEYWORD("struct") \
423 KEYWORD("class") \
424 KEYWORD("union")
425
426#define KEYWORD(s) s,
427 static const char *g_keywords[] =
428 {
429 ALL_KEYWORDS
430 };
431#undef KEYWORD
432
433#define KEYWORD(s) (sizeof(s) - 1),
434 static const int g_keyword_lengths[] =
435 {
436 ALL_KEYWORDS
437 };
438#undef KEYWORD
439
440#undef ALL_KEYWORDS
441
442 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000443 std::string type_str(view_as_type_cstr);
444
445 // Remove all instances of g_keywords that are followed by spaces
446 for (size_t i = 0; i < g_num_keywords; ++i)
447 {
448 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000449 int keyword_len = g_keyword_lengths[i];
450
451 idx = 0;
452 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000453 {
454 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000455 {
Greg Clayton84c39662011-04-27 22:04:39 +0000456 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000457 idx = 0;
458 }
459 else
460 {
461 idx += keyword_len;
462 }
Greg Clayton84c39662011-04-27 22:04:39 +0000463 }
464 }
465 bool done = type_str.empty();
466 //
467 idx = type_str.find_first_not_of (" \t");
468 if (idx > 0 && idx != std::string::npos)
469 type_str.erase (0, idx);
470 while (!done)
471 {
472 // Strip trailing spaces
473 if (type_str.empty())
474 done = true;
475 else
476 {
477 switch (type_str[type_str.size()-1])
478 {
479 case '*':
480 ++pointer_count;
481 // fall through...
482 case ' ':
483 case '\t':
484 type_str.erase(type_str.size()-1);
485 break;
486
487 case '&':
488 if (reference_count == 0)
489 {
490 reference_count = 1;
491 type_str.erase(type_str.size()-1);
492 }
493 else
494 {
495 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
496 result.SetStatus(eReturnStatusFailed);
497 return false;
498 }
499 break;
500
501 default:
502 done = true;
503 break;
504 }
505 }
506 }
507
508 ConstString lookup_type_name(type_str.c_str());
Jason Molendab57e4a12013-11-04 09:33:30 +0000509 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000510 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000511 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000512 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000513 if (sc.module_sp)
514 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000515 sc.module_sp->FindTypes (sc,
516 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000517 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000518 1,
519 type_list);
520 }
521 }
522 if (type_list.GetSize() == 0)
523 {
Greg Clayton29399a22012-04-06 17:41:13 +0000524 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000525 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000526 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000527 1,
528 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000529 }
530
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000531 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000532 {
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000533 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
534 if (tdecl)
535 {
Greg Clayton99558cc42015-08-24 23:46:31 +0000536 clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),(const lldb::clang_type_t)tdecl->getTypeForDecl());
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000537 }
Greg Clayton84c39662011-04-27 22:04:39 +0000538 }
539
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000540 if (clang_ast_type.IsValid() == false)
541 {
542 if (type_list.GetSize() == 0)
543 {
544 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
545 lookup_type_name.GetCString(),
546 view_as_type_cstr);
547 result.SetStatus(eReturnStatusFailed);
548 return false;
549 }
550 else
551 {
552 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton99558cc42015-08-24 23:46:31 +0000553 clang_ast_type = type_sp->GetFullCompilerType ();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000554 }
555 }
Greg Clayton84c39662011-04-27 22:04:39 +0000556
557 while (pointer_count > 0)
558 {
Greg Claytona1e5dc82015-08-11 22:53:00 +0000559 CompilerType pointer_type = clang_ast_type.GetPointerType();
Greg Clayton57ee3062013-07-11 22:46:58 +0000560 if (pointer_type.IsValid())
561 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000562 else
563 {
564 result.AppendError ("unable make a pointer type\n");
565 result.SetStatus(eReturnStatusFailed);
566 return false;
567 }
568 --pointer_count;
569 }
570
Enrico Granata1cd5e922015-01-28 00:07:51 +0000571 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
Greg Clayton84c39662011-04-27 22:04:39 +0000572
Greg Clayton1deb7962011-10-25 06:44:01 +0000573 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000574 {
575 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
576 view_as_type_cstr);
577 result.SetStatus(eReturnStatusFailed);
578 return false;
579 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000580
Greg Clayton1deb7962011-10-25 06:44:01 +0000581 if (!m_format_options.GetCountValue().OptionWasSet())
582 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000583 }
584 else
585 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000586 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000587 }
588
589 // Look for invalid combinations of settings
590 if (error.Fail())
591 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000592 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000593 result.SetStatus(eReturnStatusFailed);
594 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000595 }
596
Greg Clayton82f4cf42011-10-26 04:32:38 +0000597 lldb::addr_t addr;
598 size_t total_byte_size = 0;
599 if (argc == 0)
600 {
601 // Use the last address and byte size and all options as they were
602 // if no options have been set
603 addr = m_next_addr;
604 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000605 clang_ast_type = m_prev_clang_ast_type;
606 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000607 !m_memory_options.AnyOptionWasSet() &&
608 !m_outfile_options.AnyOptionWasSet() &&
609 !m_varobj_options.AnyOptionWasSet())
610 {
611 m_format_options = m_prev_format_options;
612 m_memory_options = m_prev_memory_options;
613 m_outfile_options = m_prev_outfile_options;
614 m_varobj_options = m_prev_varobj_options;
615 }
616 }
617
Greg Clayton1deb7962011-10-25 06:44:01 +0000618 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000619
620 // TODO For non-8-bit byte addressable architectures this needs to be
621 // revisited to fully support all lldb's range of formatting options.
622 // Furthermore code memory reads (for those architectures) will not
623 // be correctly formatted even w/o formatting options.
624 size_t item_byte_size =
625 target->GetArchitecture().GetDataByteSize() > 1 ?
626 target->GetArchitecture().GetDataByteSize() :
627 m_format_options.GetByteSizeValue().GetCurrentValue();
628
Greg Clayton68ebae62011-04-28 20:55:26 +0000629 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000630
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000631 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000632 {
633 total_byte_size = item_count * item_byte_size;
634 if (total_byte_size == 0)
635 total_byte_size = 32;
636 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000637
Greg Clayton82f4cf42011-10-26 04:32:38 +0000638 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000639 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000640
641 if (addr == LLDB_INVALID_ADDRESS)
642 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000643 result.AppendError("invalid start address expression.");
644 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000645 result.SetStatus(eReturnStatusFailed);
646 return false;
647 }
648
649 if (argc == 2)
650 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000651 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000652 if (end_addr == LLDB_INVALID_ADDRESS)
653 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000654 result.AppendError("invalid end address expression.");
655 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000656 result.SetStatus(eReturnStatusFailed);
657 return false;
658 }
659 else if (end_addr <= addr)
660 {
Daniel Malead01b2952012-11-29 21:49:15 +0000661 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 +0000662 result.SetStatus(eReturnStatusFailed);
663 return false;
664 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000665 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000666 {
Greg Clayton6fea17e2014-03-03 19:15:20 +0000667 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 +0000668 result.SetStatus(eReturnStatusFailed);
669 return false;
670 }
671
672 total_byte_size = end_addr - addr;
673 item_count = total_byte_size / item_byte_size;
674 }
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000675
Enrico Granatad325bf92013-06-04 22:54:16 +0000676 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
677
678 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000679 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000680 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
681 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
682 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 +0000683 return false;
684 }
685
Greg Clayton84c39662011-04-27 22:04:39 +0000686 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000687 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000688 if (clang_ast_type.GetOpaqueQualType())
689 {
690 // Make sure we don't display our type as ASCII bytes like the default memory read
691 if (m_format_options.GetFormatValue().OptionWasSet() == false)
692 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
693
Enrico Granata1cd5e922015-01-28 00:07:51 +0000694 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000695 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000696 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000697 {
Greg Clayton84c39662011-04-27 22:04:39 +0000698 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000699 if (data_sp->GetBytes() == NULL)
700 {
Virgile Belloffeba252014-03-08 17:15:35 +0000701 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 +0000702 result.SetStatus(eReturnStatusFailed);
703 return false;
704 }
705
Greg Claytone72dfb32012-02-24 01:59:29 +0000706 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000707 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000708 if (bytes_read == 0)
709 {
Greg Clayton57f06302012-05-25 17:05:55 +0000710 const char *error_cstr = error.AsCString();
711 if (error_cstr && error_cstr[0])
712 {
713 result.AppendError(error_cstr);
714 }
715 else
716 {
Daniel Malead01b2952012-11-29 21:49:15 +0000717 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000718 }
Greg Clayton84c39662011-04-27 22:04:39 +0000719 result.SetStatus(eReturnStatusFailed);
720 return false;
721 }
722
723 if (bytes_read < total_byte_size)
Greg Clayton6fea17e2014-03-03 19:15:20 +0000724 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 +0000725 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000726 else
727 {
728 // we treat c-strings as a special case because they do not have a fixed size
729 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
730 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
731 else
732 item_byte_size = target->GetMaximumSizeOfStringSummary();
733 if (!m_format_options.GetCountValue().OptionWasSet())
734 item_count = 1;
735 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000736 if (data_sp->GetBytes() == NULL)
737 {
738 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));
739 result.SetStatus(eReturnStatusFailed);
740 return false;
741 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000742 uint8_t *data_ptr = data_sp->GetBytes();
743 auto data_addr = addr;
744 auto count = item_count;
745 item_count = 0;
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000746 bool break_on_no_NULL = false;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000747 while (item_count < count)
748 {
749 std::string buffer;
750 buffer.resize(item_byte_size+1,0);
751 Error error;
752 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
753 if (error.Fail())
754 {
755 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
756 result.SetStatus(eReturnStatusFailed);
757 return false;
758 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000759
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000760 if (item_byte_size == read)
761 {
762 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 +0000763 --read;
764 break_on_no_NULL = true;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000765 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000766 else
767 ++read; // account for final NULL byte
768
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000769 memcpy(data_ptr, &buffer[0], read);
770 data_ptr += read;
771 data_addr += read;
772 bytes_read += read;
773 item_count++; // if we break early we know we only read item_count strings
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000774
775 if (break_on_no_NULL)
776 break;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000777 }
778 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
779 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000780
Greg Clayton2e1f7452012-12-15 02:08:17 +0000781 m_next_addr = addr + bytes_read;
782 m_prev_byte_size = bytes_read;
783 m_prev_format_options = m_format_options;
784 m_prev_memory_options = m_memory_options;
785 m_prev_outfile_options = m_outfile_options;
786 m_prev_varobj_options = m_varobj_options;
787 m_prev_clang_ast_type = clang_ast_type;
788
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000789 StreamFile outfile_stream;
790 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000791 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
792 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000793 {
794 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000795 outfile_spec.GetPath (path, sizeof(path));
796
797 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
798 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
799 if (append)
800 open_options |= File::eOpenOptionAppend;
801
802 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000803 {
Greg Clayton84c39662011-04-27 22:04:39 +0000804 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000805 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000806 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000807 if (bytes_written > 0)
808 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000809 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000810 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000811 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000812 path);
813 return true;
814 }
815 else
816 {
Daniel Malead01b2952012-11-29 21:49:15 +0000817 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000818 result.SetStatus(eReturnStatusFailed);
819 return false;
820 }
821 }
822 else
823 {
824 // We are going to write ASCII to the file just point the
825 // output_stream to our outfile_stream...
826 output_stream = &outfile_stream;
827 }
828 }
829 else
830 {
Greg Clayton84c39662011-04-27 22:04:39 +0000831 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000832 result.SetStatus(eReturnStatusFailed);
833 return false;
834 }
835 }
836 else
837 {
838 output_stream = &result.GetOutputStream();
839 }
840
Greg Clayton84c39662011-04-27 22:04:39 +0000841
Greg Claytonf9fc6092013-01-09 19:44:40 +0000842 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000843 if (clang_ast_type.GetOpaqueQualType())
844 {
845 for (uint32_t i = 0; i<item_count; ++i)
846 {
847 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000848 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000849 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000850 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000851 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000852 name_strm.GetString().c_str(),
853 address,
854 clang_ast_type));
855 if (valobj_sp)
856 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000857 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000858 if (format != eFormatDefault)
859 valobj_sp->SetFormat (format);
860
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000861 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000862
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000863 valobj_sp->Dump(*output_stream,options);
Greg Clayton84c39662011-04-27 22:04:39 +0000864 }
865 else
866 {
867 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
868 view_as_type_cstr,
869 name_strm.GetString().c_str());
870 result.SetStatus(eReturnStatusFailed);
871 return false;
872 }
873 }
874 return true;
875 }
876
877 result.SetStatus(eReturnStatusSuccessFinishResult);
878 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000879 target->GetArchitecture().GetByteOrder(),
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000880 target->GetArchitecture().GetAddressByteSize(),
881 target->GetArchitecture().GetDataByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000882
883 Format format = m_format_options.GetFormat();
884 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
Enrico Granata0947a6e2013-10-29 23:04:29 +0000885 && (item_byte_size != 1))
Enrico Granata31898912013-05-21 17:39:04 +0000886 {
Enrico Granata0947a6e2013-10-29 23:04:29 +0000887 // if a count was not passed, or it is 1
888 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
889 {
890 // this turns requests such as
891 // memory read -fc -s10 -c1 *charPtrPtr
892 // which make no sense (what is a char of size 10?)
893 // into a request for fetching 10 chars of size 1 from the same memory location
894 format = eFormatCharArray;
895 item_count = item_byte_size;
896 item_byte_size = 1;
897 }
898 else
899 {
900 // here we passed a count, and it was not 1
901 // so we have a byte_size and a count
902 // we could well multiply those, but instead let's just fail
Greg Clayton6fea17e2014-03-03 19:15:20 +0000903 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
Enrico Granata0947a6e2013-10-29 23:04:29 +0000904 result.SetStatus(eReturnStatusFailed);
905 return false;
906 }
Enrico Granata31898912013-05-21 17:39:04 +0000907 }
Greg Clayton84c39662011-04-27 22:04:39 +0000908
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000909 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000910 size_t bytes_dumped = data.Dump (output_stream,
911 0,
Enrico Granata31898912013-05-21 17:39:04 +0000912 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000913 item_byte_size,
914 item_count,
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000915 num_per_line / target->GetArchitecture().GetDataByteSize(),
Greg Claytonc7bece562013-01-25 18:06:21 +0000916 addr,
917 0,
918 0,
919 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000920 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000921 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000922 return true;
923 }
924
Greg Clayton84c39662011-04-27 22:04:39 +0000925 OptionGroupOptions m_option_group;
926 OptionGroupFormat m_format_options;
927 OptionGroupReadMemory m_memory_options;
928 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000929 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000930 lldb::addr_t m_next_addr;
931 lldb::addr_t m_prev_byte_size;
932 OptionGroupFormat m_prev_format_options;
933 OptionGroupReadMemory m_prev_memory_options;
934 OptionGroupOutputFile m_prev_outfile_options;
935 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Claytona1e5dc82015-08-11 22:53:00 +0000936 CompilerType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000937};
938
Enrico Granata53468432013-11-13 02:18:44 +0000939OptionDefinition
940g_memory_find_option_table[] =
941{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000942 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
943 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
944 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."},
945 { 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 +0000946};
947
Enrico Granata53468432013-11-13 02:18:44 +0000948//----------------------------------------------------------------------
949// Find the specified data in memory
950//----------------------------------------------------------------------
951class CommandObjectMemoryFind : public CommandObjectParsed
952{
953public:
954
955 class OptionGroupFindMemory : public OptionGroup
956 {
957 public:
958 OptionGroupFindMemory () :
959 OptionGroup(),
960 m_count(1),
Enrico Granata8d81a842013-11-13 20:08:30 +0000961 m_offset(0)
Enrico Granata53468432013-11-13 02:18:44 +0000962 {
963 }
964
965 virtual
966 ~OptionGroupFindMemory ()
967 {
968 }
969
970 virtual uint32_t
971 GetNumDefinitions ()
972 {
973 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
974 }
975
976 virtual const OptionDefinition*
977 GetDefinitions ()
978 {
979 return g_memory_find_option_table;
980 }
981
982 virtual Error
983 SetOptionValue (CommandInterpreter &interpreter,
984 uint32_t option_idx,
985 const char *option_arg)
986 {
987 Error error;
988 const int short_option = g_memory_find_option_table[option_idx].short_option;
989
990 switch (short_option)
991 {
992 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000993 m_expr.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +0000994 break;
995
996 case 's':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000997 m_string.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +0000998 break;
999
1000 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001001 if (m_count.SetValueFromString(option_arg).Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001002 error.SetErrorString("unrecognized value for count");
1003 break;
1004
Enrico Granata8d81a842013-11-13 20:08:30 +00001005 case 'o':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001006 if (m_offset.SetValueFromString(option_arg).Fail())
Enrico Granata8d81a842013-11-13 20:08:30 +00001007 error.SetErrorString("unrecognized value for dump-offset");
1008 break;
1009
Enrico Granata53468432013-11-13 02:18:44 +00001010 default:
1011 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1012 break;
1013 }
1014 return error;
1015 }
1016
1017 virtual void
1018 OptionParsingStarting (CommandInterpreter &interpreter)
1019 {
1020 m_expr.Clear();
1021 m_string.Clear();
1022 m_count.Clear();
Enrico Granata53468432013-11-13 02:18:44 +00001023 }
1024
1025 OptionValueString m_expr;
1026 OptionValueString m_string;
1027 OptionValueUInt64 m_count;
Enrico Granata8d81a842013-11-13 20:08:30 +00001028 OptionValueUInt64 m_offset;
Enrico Granata53468432013-11-13 02:18:44 +00001029 };
1030
1031 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1032 CommandObjectParsed (interpreter,
1033 "memory find",
1034 "Find a value in the memory of the process being debugged.",
1035 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001036 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Enrico Granata53468432013-11-13 02:18:44 +00001037 m_option_group (interpreter),
1038 m_memory_options ()
1039 {
1040 CommandArgumentEntry arg1;
1041 CommandArgumentEntry arg2;
1042 CommandArgumentData addr_arg;
1043 CommandArgumentData value_arg;
1044
1045 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001046 addr_arg.arg_type = eArgTypeAddressOrExpression;
Enrico Granata53468432013-11-13 02:18:44 +00001047 addr_arg.arg_repetition = eArgRepeatPlain;
1048
1049 // There is only one variant this argument could be; put it into the argument entry.
1050 arg1.push_back (addr_arg);
1051
1052 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001053 value_arg.arg_type = eArgTypeAddressOrExpression;
1054 value_arg.arg_repetition = eArgRepeatPlain;
Enrico Granata53468432013-11-13 02:18:44 +00001055
1056 // There is only one variant this argument could be; put it into the argument entry.
1057 arg2.push_back (value_arg);
1058
1059 // Push the data for the first argument into the m_arguments vector.
1060 m_arguments.push_back (arg1);
1061 m_arguments.push_back (arg2);
1062
1063 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1064 m_option_group.Finalize();
1065 }
1066
1067 virtual
1068 ~CommandObjectMemoryFind ()
1069 {
1070 }
1071
1072 Options *
1073 GetOptions ()
1074 {
1075 return &m_option_group;
1076 }
1077
1078protected:
1079 virtual bool
1080 DoExecute (Args& command, CommandReturnObject &result)
1081 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001082 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Enrico Granata53468432013-11-13 02:18:44 +00001083 Process *process = m_exe_ctx.GetProcessPtr();
1084
1085 const size_t argc = command.GetArgumentCount();
1086
1087 if (argc != 2)
1088 {
Enrico Granata6e49c482013-11-13 02:22:24 +00001089 result.AppendError("two addresses needed for memory find");
Enrico Granata53468432013-11-13 02:18:44 +00001090 return false;
1091 }
1092
1093 Error error;
1094 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1095 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1096 {
1097 result.AppendError("invalid low address");
1098 return false;
1099 }
1100 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1101 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1102 {
Ed Maste47a8a5e2014-09-06 11:29:08 +00001103 result.AppendError("invalid high address");
Enrico Granata53468432013-11-13 02:18:44 +00001104 return false;
1105 }
1106
1107 if (high_addr <= low_addr)
1108 {
1109 result.AppendError("starting address must be smaller than ending address");
1110 return false;
1111 }
1112
1113 lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1114
1115 DataBufferHeap buffer;
1116
1117 if (m_memory_options.m_string.OptionWasSet())
1118 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1119 else if (m_memory_options.m_expr.OptionWasSet())
1120 {
1121 StackFrame* frame = m_exe_ctx.GetFramePtr();
1122 ValueObjectSP result_sp;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001123 if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
1124 result_sp.get())
Enrico Granata53468432013-11-13 02:18:44 +00001125 {
1126 uint64_t value = result_sp->GetValueAsUnsigned(0);
Greg Clayton99558cc42015-08-24 23:46:31 +00001127 switch (result_sp->GetCompilerType().GetByteSize(nullptr))
Enrico Granata53468432013-11-13 02:18:44 +00001128 {
1129 case 1: {
1130 uint8_t byte = (uint8_t)value;
1131 buffer.CopyData(&byte,1);
1132 }
1133 break;
1134 case 2: {
1135 uint16_t word = (uint16_t)value;
1136 buffer.CopyData(&word,2);
1137 }
1138 break;
1139 case 4: {
1140 uint32_t lword = (uint32_t)value;
1141 buffer.CopyData(&lword,4);
1142 }
1143 break;
1144 case 8: {
1145 buffer.CopyData(&value, 8);
1146 }
1147 break;
1148 case 3:
1149 case 5:
1150 case 6:
1151 case 7:
1152 result.AppendError("unknown type. pass a string instead");
1153 return false;
1154 default:
Enrico Granata0b3b9872015-08-03 18:51:39 +00001155 result.AppendError("result size larger than 8 bytes. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001156 return false;
1157 }
1158 }
1159 else
1160 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001161 result.AppendError("expression evaluation failed. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001162 return false;
1163 }
1164 }
1165 else
1166 {
1167 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1168 return false;
1169 }
1170
1171 size_t count = m_memory_options.m_count.GetCurrentValue();
1172 found_location = low_addr;
1173 bool ever_found = false;
1174 while (count)
1175 {
1176 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1177 if (found_location == LLDB_INVALID_ADDRESS)
1178 {
1179 if (!ever_found)
1180 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001181 result.AppendMessage("data not found within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001182 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1183 }
1184 else
Enrico Granata0b3b9872015-08-03 18:51:39 +00001185 result.AppendMessage("no more matches within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001186 break;
1187 }
Enrico Granata0b3b9872015-08-03 18:51:39 +00001188 result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location);
Enrico Granata8d81a842013-11-13 20:08:30 +00001189
1190 DataBufferHeap dumpbuffer(32,0);
1191 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1192 if (!error.Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001193 {
Enrico Granata8d81a842013-11-13 20:08:30 +00001194 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1195 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1196 result.GetOutputStream().EOL();
Enrico Granata53468432013-11-13 02:18:44 +00001197 }
Enrico Granata8d81a842013-11-13 20:08:30 +00001198
Enrico Granata53468432013-11-13 02:18:44 +00001199 --count;
1200 found_location++;
1201 ever_found = true;
1202 }
1203
1204 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1205 return true;
1206 }
1207
1208 lldb::addr_t
1209 Search (lldb::addr_t low,
1210 lldb::addr_t high,
1211 uint8_t* buffer,
1212 size_t buffer_size)
1213 {
1214 Process *process = m_exe_ctx.GetProcessPtr();
1215 DataBufferHeap heap(buffer_size, 0);
Enrico Granata53468432013-11-13 02:18:44 +00001216 for (auto ptr = low;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001217 ptr < high;
1218 ptr++)
Enrico Granata53468432013-11-13 02:18:44 +00001219 {
1220 Error error;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001221 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
Enrico Granata53468432013-11-13 02:18:44 +00001222 if (error.Fail())
1223 return LLDB_INVALID_ADDRESS;
1224 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
Enrico Granata0b3b9872015-08-03 18:51:39 +00001225 return ptr;
Enrico Granata53468432013-11-13 02:18:44 +00001226 }
1227 return LLDB_INVALID_ADDRESS;
1228 }
1229
1230 OptionGroupOptions m_option_group;
1231 OptionGroupFindMemory m_memory_options;
1232};
1233
Greg Clayton1deb7962011-10-25 06:44:01 +00001234
1235OptionDefinition
1236g_memory_write_option_table[] =
1237{
Zachary Turnerd37221d2014-07-09 16:31:49 +00001238{ 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 +00001239{ 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 +00001240};
1241
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001242//----------------------------------------------------------------------
1243// Write memory to the inferior process
1244//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001245class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001246{
1247public:
1248
Greg Clayton1deb7962011-10-25 06:44:01 +00001249 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001250 {
1251 public:
Greg Clayton1deb7962011-10-25 06:44:01 +00001252 OptionGroupWriteMemory () :
1253 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001254 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001255 }
1256
1257 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +00001258 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001259 {
1260 }
1261
Greg Clayton1deb7962011-10-25 06:44:01 +00001262 virtual uint32_t
1263 GetNumDefinitions ()
1264 {
1265 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1266 }
Enrico Granata53468432013-11-13 02:18:44 +00001267
Greg Clayton1deb7962011-10-25 06:44:01 +00001268 virtual const OptionDefinition*
1269 GetDefinitions ()
1270 {
1271 return g_memory_write_option_table;
1272 }
Enrico Granata53468432013-11-13 02:18:44 +00001273
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001274 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +00001275 SetOptionValue (CommandInterpreter &interpreter,
1276 uint32_t option_idx,
1277 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001278 {
1279 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001280 const int short_option = g_memory_write_option_table[option_idx].short_option;
Enrico Granata53468432013-11-13 02:18:44 +00001281
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001282 switch (short_option)
1283 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001284 case 'i':
1285 m_infile.SetFile (option_arg, true);
1286 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001287 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001288 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +00001289 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001290 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001291 break;
Enrico Granata53468432013-11-13 02:18:44 +00001292
Greg Clayton1deb7962011-10-25 06:44:01 +00001293 case 'o':
1294 {
1295 bool success;
Vince Harron5275aaa2015-01-15 20:08:35 +00001296 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
Greg Clayton1deb7962011-10-25 06:44:01 +00001297 if (!success)
1298 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001299 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +00001300 }
1301 }
1302 break;
1303
1304 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001305 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +00001306 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001307 }
1308 return error;
1309 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001310
1311 virtual void
1312 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001313 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001314 m_infile.Clear();
1315 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001316 }
1317
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001318 FileSpec m_infile;
1319 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001320 };
1321
Greg Claytona7015092010-09-18 01:14:36 +00001322 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001323 CommandObjectParsed (interpreter,
1324 "memory write",
1325 "Write to the memory of the process being debugged.",
1326 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001327 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001328 m_option_group (interpreter),
1329 m_format_options (eFormatBytes, 1, UINT64_MAX),
1330 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001331 {
Caroline Tice405fe672010-10-04 22:28:36 +00001332 CommandArgumentEntry arg1;
1333 CommandArgumentEntry arg2;
1334 CommandArgumentData addr_arg;
1335 CommandArgumentData value_arg;
1336
1337 // Define the first (and only) variant of this arg.
1338 addr_arg.arg_type = eArgTypeAddress;
1339 addr_arg.arg_repetition = eArgRepeatPlain;
1340
1341 // There is only one variant this argument could be; put it into the argument entry.
1342 arg1.push_back (addr_arg);
1343
1344 // Define the first (and only) variant of this arg.
1345 value_arg.arg_type = eArgTypeValue;
1346 value_arg.arg_repetition = eArgRepeatPlus;
1347
1348 // There is only one variant this argument could be; put it into the argument entry.
1349 arg2.push_back (value_arg);
1350
1351 // Push the data for the first argument into the m_arguments vector.
1352 m_arguments.push_back (arg1);
1353 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001354
1355 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1356 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1357 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1358 m_option_group.Finalize();
1359
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001360 }
1361
1362 virtual
1363 ~CommandObjectMemoryWrite ()
1364 {
1365 }
1366
1367 Options *
1368 GetOptions ()
1369 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001370 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001371 }
1372
1373 bool
1374 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1375 {
1376 if (total_byte_size > 8)
1377 return false;
1378
1379 if (total_byte_size == 8)
1380 return true;
1381
1382 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1383 return uval64 <= max;
1384 }
1385
1386 bool
1387 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1388 {
1389 if (total_byte_size > 8)
1390 return false;
1391
1392 if (total_byte_size == 8)
1393 return true;
1394
1395 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1396 const int64_t min = ~(max);
1397 return min <= sval64 && sval64 <= max;
1398 }
1399
Jim Ingham5a988412012-06-08 21:56:10 +00001400protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001401 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001402 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001403 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001404 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +00001405 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001406
1407 const size_t argc = command.GetArgumentCount();
1408
Greg Clayton1deb7962011-10-25 06:44:01 +00001409 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001410 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001411 if (argc < 1)
1412 {
1413 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1414 result.SetStatus(eReturnStatusFailed);
1415 return false;
1416 }
1417 }
1418 else if (argc < 2)
1419 {
1420 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 +00001421 result.SetStatus(eReturnStatusFailed);
1422 return false;
1423 }
1424
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001425 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001426 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1427 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001428
Greg Clayton1deb7962011-10-25 06:44:01 +00001429 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1430 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001431
Greg Claytonb9d5df52012-12-06 22:49:16 +00001432 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001433 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001434 command.GetArgumentAtIndex(0),
1435 LLDB_INVALID_ADDRESS,
1436 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001437
1438 if (addr == LLDB_INVALID_ADDRESS)
1439 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001440 result.AppendError("invalid address expression\n");
1441 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001442 result.SetStatus(eReturnStatusFailed);
1443 return false;
1444 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001445
Greg Clayton1deb7962011-10-25 06:44:01 +00001446 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001447 {
1448 size_t length = SIZE_MAX;
Jason Molenda250b1b892015-02-03 23:39:47 +00001449 if (item_byte_size > 1)
Greg Clayton1deb7962011-10-25 06:44:01 +00001450 length = item_byte_size;
1451 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001452 if (data_sp)
1453 {
1454 length = data_sp->GetByteSize();
1455 if (length > 0)
1456 {
1457 Error error;
1458 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1459
1460 if (bytes_written == length)
1461 {
1462 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001463 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001464 result.SetStatus(eReturnStatusSuccessFinishResult);
1465 }
1466 else if (bytes_written > 0)
1467 {
1468 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001469 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 +00001470 result.SetStatus(eReturnStatusSuccessFinishResult);
1471 }
1472 else
1473 {
Daniel Malead01b2952012-11-29 21:49:15 +00001474 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001475 result.SetStatus(eReturnStatusFailed);
1476 }
1477 }
1478 }
1479 else
1480 {
1481 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1482 result.SetStatus(eReturnStatusFailed);
1483 }
1484 return result.Succeeded();
1485 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001486 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001487 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001488 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001489 item_byte_size = buffer.GetAddressByteSize();
1490 else
1491 item_byte_size = 1;
1492 }
1493
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001494 command.Shift(); // shift off the address argument
1495 uint64_t uval64;
1496 int64_t sval64;
1497 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001498 const size_t num_value_args = command.GetArgumentCount();
1499 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001500 {
1501 const char *value_str = command.GetArgumentAtIndex(i);
1502
Greg Clayton1deb7962011-10-25 06:44:01 +00001503 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001504 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001505 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001506 case eFormatFloat: // TODO: add support for floats soon
1507 case eFormatCharPrintable:
1508 case eFormatBytesWithASCII:
1509 case eFormatComplex:
1510 case eFormatEnum:
1511 case eFormatUnicode16:
1512 case eFormatUnicode32:
1513 case eFormatVectorOfChar:
1514 case eFormatVectorOfSInt8:
1515 case eFormatVectorOfUInt8:
1516 case eFormatVectorOfSInt16:
1517 case eFormatVectorOfUInt16:
1518 case eFormatVectorOfSInt32:
1519 case eFormatVectorOfUInt32:
1520 case eFormatVectorOfSInt64:
1521 case eFormatVectorOfUInt64:
1522 case eFormatVectorOfFloat32:
1523 case eFormatVectorOfFloat64:
1524 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001525 case eFormatOSType:
1526 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001527 case eFormatAddressInfo:
1528 case eFormatHexFloat:
1529 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001530 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001531 result.AppendError("unsupported format for writing memory");
1532 result.SetStatus(eReturnStatusFailed);
1533 return false;
1534
1535 case eFormatDefault:
1536 case eFormatBytes:
1537 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001538 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001539 case eFormatPointer:
1540
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001541 // Decode hex bytes
Vince Harron5275aaa2015-01-15 20:08:35 +00001542 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001543 if (!success)
1544 {
1545 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1546 result.SetStatus(eReturnStatusFailed);
1547 return false;
1548 }
1549 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1550 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001551 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 +00001552 result.SetStatus(eReturnStatusFailed);
1553 return false;
1554 }
1555 buffer.PutMaxHex64 (uval64, item_byte_size);
1556 break;
1557
1558 case eFormatBoolean:
1559 uval64 = Args::StringToBoolean(value_str, false, &success);
1560 if (!success)
1561 {
1562 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1563 result.SetStatus(eReturnStatusFailed);
1564 return false;
1565 }
1566 buffer.PutMaxHex64 (uval64, item_byte_size);
1567 break;
1568
1569 case eFormatBinary:
Vince Harron5275aaa2015-01-15 20:08:35 +00001570 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001571 if (!success)
1572 {
1573 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1574 result.SetStatus(eReturnStatusFailed);
1575 return false;
1576 }
1577 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1578 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001579 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 +00001580 result.SetStatus(eReturnStatusFailed);
1581 return false;
1582 }
1583 buffer.PutMaxHex64 (uval64, item_byte_size);
1584 break;
1585
Greg Clayton4e4294b2011-06-17 23:50:44 +00001586 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001587 case eFormatChar:
1588 case eFormatCString:
1589 if (value_str[0])
1590 {
1591 size_t len = strlen (value_str);
1592 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001593 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001594 ++len;
1595 Error error;
1596 if (process->WriteMemory (addr, value_str, len, error) == len)
1597 {
1598 addr += len;
1599 }
1600 else
1601 {
Daniel Malead01b2952012-11-29 21:49:15 +00001602 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001603 result.SetStatus(eReturnStatusFailed);
1604 return false;
1605 }
1606 }
1607 break;
1608
1609 case eFormatDecimal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001610 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001611 if (!success)
1612 {
1613 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1614 result.SetStatus(eReturnStatusFailed);
1615 return false;
1616 }
1617 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1618 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001619 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 +00001620 result.SetStatus(eReturnStatusFailed);
1621 return false;
1622 }
1623 buffer.PutMaxHex64 (sval64, item_byte_size);
1624 break;
1625
1626 case eFormatUnsigned:
Vince Harron5275aaa2015-01-15 20:08:35 +00001627 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001628 if (!success)
1629 {
1630 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1631 result.SetStatus(eReturnStatusFailed);
1632 return false;
1633 }
1634 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1635 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001636 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 +00001637 result.SetStatus(eReturnStatusFailed);
1638 return false;
1639 }
1640 buffer.PutMaxHex64 (uval64, item_byte_size);
1641 break;
1642
1643 case eFormatOctal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001644 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001645 if (!success)
1646 {
1647 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1648 result.SetStatus(eReturnStatusFailed);
1649 return false;
1650 }
1651 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1652 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001653 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 +00001654 result.SetStatus(eReturnStatusFailed);
1655 return false;
1656 }
1657 buffer.PutMaxHex64 (uval64, item_byte_size);
1658 break;
1659 }
1660 }
1661
1662 if (!buffer.GetString().empty())
1663 {
1664 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001665 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001666 return true;
1667 else
1668 {
Daniel Malead01b2952012-11-29 21:49:15 +00001669 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001670 result.SetStatus(eReturnStatusFailed);
1671 return false;
1672 }
1673 }
1674 return true;
1675 }
1676
Greg Clayton1deb7962011-10-25 06:44:01 +00001677 OptionGroupOptions m_option_group;
1678 OptionGroupFormat m_format_options;
1679 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001680};
1681
Kuba Breckabeed8212014-09-04 01:03:18 +00001682//----------------------------------------------------------------------
1683// Get malloc/free history of a memory address.
1684//----------------------------------------------------------------------
1685class CommandObjectMemoryHistory : public CommandObjectParsed
1686{
1687public:
1688
1689 CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1690 CommandObjectParsed (interpreter,
1691 "memory history",
1692 "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1693 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001694 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | eCommandProcessMustBeLaunched)
Kuba Breckabeed8212014-09-04 01:03:18 +00001695 {
1696 CommandArgumentEntry arg1;
1697 CommandArgumentData addr_arg;
1698
1699 // Define the first (and only) variant of this arg.
1700 addr_arg.arg_type = eArgTypeAddress;
1701 addr_arg.arg_repetition = eArgRepeatPlain;
1702
1703 // There is only one variant this argument could be; put it into the argument entry.
1704 arg1.push_back (addr_arg);
1705
1706 // Push the data for the first argument into the m_arguments vector.
1707 m_arguments.push_back (arg1);
1708 }
1709
1710 virtual
1711 ~CommandObjectMemoryHistory ()
1712 {
1713 }
1714
1715 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
1716 {
1717 return m_cmd_name.c_str();
1718 }
1719
1720protected:
1721 virtual bool
1722 DoExecute (Args& command, CommandReturnObject &result)
1723 {
1724 const size_t argc = command.GetArgumentCount();
1725
1726 if (argc == 0 || argc > 1)
1727 {
1728 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1729 result.SetStatus(eReturnStatusFailed);
1730 return false;
1731 }
1732
1733 Error error;
1734 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1735 command.GetArgumentAtIndex(0),
1736 LLDB_INVALID_ADDRESS,
1737 &error);
1738
1739 if (addr == LLDB_INVALID_ADDRESS)
1740 {
1741 result.AppendError("invalid address expression");
1742 result.AppendError(error.AsCString());
1743 result.SetStatus(eReturnStatusFailed);
1744 return false;
1745 }
1746
1747 Stream *output_stream = &result.GetOutputStream();
1748
1749 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1750 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1751
1752 if (! memory_history.get())
1753 {
1754 result.AppendError("no available memory history provider");
1755 result.SetStatus(eReturnStatusFailed);
1756 return false;
1757 }
1758
1759 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1760
1761 for (auto thread : thread_list) {
1762 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1763 }
1764
1765 result.SetStatus(eReturnStatusSuccessFinishResult);
1766
1767 return true;
1768 }
1769
1770};
1771
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001772
1773//-------------------------------------------------------------------------
1774// CommandObjectMemory
1775//-------------------------------------------------------------------------
1776
Greg Clayton66111032010-06-23 01:19:29 +00001777CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001778 CommandObjectMultiword (interpreter,
1779 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001780 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001781 "memory <subcommand> [<subcommand-options>]")
1782{
Enrico Granata53468432013-11-13 02:18:44 +00001783 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001784 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1785 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Kuba Breckabeed8212014-09-04 01:03:18 +00001786 LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001787}
1788
1789CommandObjectMemory::~CommandObjectMemory ()
1790{
1791}