blob: 4725a4da6578fc2fc1ceceba28ec57d374d4185d [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012#include "CommandObjectMemory.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000020#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000021#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000023#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton66111032010-06-23 01:19:29 +000024#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000026#include "lldb/Interpreter/CommandInterpreter.h"
27#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000028#include "lldb/Interpreter/OptionGroupFormat.h"
29#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000030#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000031#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton1f746072012-08-29 21:13:06 +000032#include "lldb/Symbol/TypeList.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033#include "lldb/Target/Process.h"
Greg Clayton84c39662011-04-27 22:04:39 +000034#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035
36using namespace lldb;
37using namespace lldb_private;
38
Greg Clayton68ebae62011-04-28 20:55:26 +000039static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000040g_option_table[] =
41{
Greg Clayton84c39662011-04-27 22:04:39 +000042 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
43 { LLDB_OPT_SET_2, false, "binary" ,'b', no_argument , NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
Sean Callanan3d654b32012-09-24 22:25:51 +000044 { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton2346fcf2012-11-02 21:14:58 +000045 { LLDB_OPT_SET_1|
46 LLDB_OPT_SET_2|
Enrico Granatad325bf92013-06-04 22:54:16 +000047 LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
Greg Clayton84c39662011-04-27 22:04:39 +000048};
49
50
51
52class OptionGroupReadMemory : public OptionGroup
53{
54public:
55
56 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000057 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000058 m_output_as_binary (false),
59 m_view_as_type()
60 {
61 }
62
63 virtual
64 ~OptionGroupReadMemory ()
65 {
66 }
67
68
69 virtual uint32_t
70 GetNumDefinitions ()
71 {
72 return sizeof (g_option_table) / sizeof (OptionDefinition);
73 }
74
75 virtual const OptionDefinition*
76 GetDefinitions ()
77 {
78 return g_option_table;
79 }
80
81 virtual Error
82 SetOptionValue (CommandInterpreter &interpreter,
83 uint32_t option_idx,
84 const char *option_arg)
85 {
86 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000087 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000088
89 switch (short_option)
90 {
91 case 'l':
92 error = m_num_per_line.SetValueFromCString (option_arg);
93 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +000094 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +000095 break;
Greg Clayton1deb7962011-10-25 06:44:01 +000096
Greg Clayton84c39662011-04-27 22:04:39 +000097 case 'b':
98 m_output_as_binary = true;
99 break;
100
101 case 't':
102 error = m_view_as_type.SetValueFromCString (option_arg);
103 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000104
105 case 'r':
106 m_force = true;
107 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000108
109 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000110 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000111 break;
112 }
113 return error;
114 }
115
116 virtual void
117 OptionParsingStarting (CommandInterpreter &interpreter)
118 {
Greg Clayton84c39662011-04-27 22:04:39 +0000119 m_num_per_line.Clear();
120 m_output_as_binary = false;
121 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000122 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000123 }
124
Greg Clayton68ebae62011-04-28 20:55:26 +0000125 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000126 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000127 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000128 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000129 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
130 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000131 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000132 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000133 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000134
Greg Clayton68ebae62011-04-28 20:55:26 +0000135 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000136 {
137 default:
138 break;
139
140 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000141 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000142 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000143 if (!num_per_line_option_set)
144 m_num_per_line = 1;
145 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000146 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000147 break;
148
149 case eFormatCString:
150 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000151
152 case eFormatInstruction:
153 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000154 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000155 m_num_per_line = 1;
156 break;
157
158 case eFormatAddressInfo:
159 if (!byte_size_option_set)
160 byte_size_value = target->GetArchitecture().GetAddressByteSize();
161 m_num_per_line = 1;
162 if (!count_option_set)
163 format_options.GetCountValue() = 8;
164 break;
165
Greg Clayton84c39662011-04-27 22:04:39 +0000166 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000167 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000168 if (!num_per_line_option_set)
169 m_num_per_line = 4;
170 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000171 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000172 break;
173
174 case eFormatBinary:
175 case eFormatFloat:
176 case eFormatOctal:
177 case eFormatDecimal:
178 case eFormatEnum:
179 case eFormatUnicode16:
180 case eFormatUnicode32:
181 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000182 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000183 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000184 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000185 if (!num_per_line_option_set)
186 m_num_per_line = 1;
187 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000188 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000189 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000190
Greg Clayton84c39662011-04-27 22:04:39 +0000191 case eFormatBytes:
192 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000193 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000194 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000195 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000196 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000197 "\tconsider using a different display format or don't specify the byte size",
198 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000199 }
200 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000201 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000202 if (!num_per_line_option_set)
203 m_num_per_line = 16;
204 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000205 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000206 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000207 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000208 case eFormatChar:
209 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000210 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000211 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000212 if (!num_per_line_option_set)
213 m_num_per_line = 32;
214 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000215 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000216 break;
217 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000218 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000219 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000220 if (!num_per_line_option_set)
221 m_num_per_line = 1;
222 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000223 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000224 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000225 case eFormatComplexInteger:
226 if (!byte_size_option_set)
227 byte_size_value = 8;
228 if (!num_per_line_option_set)
229 m_num_per_line = 1;
230 if (!count_option_set)
231 format_options.GetCountValue() = 8;
232 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000233 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000234 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000235 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000236 if (!num_per_line_option_set)
237 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000238 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000239 {
240 case 1:
241 case 2:
242 m_num_per_line = 8;
243 break;
244 case 4:
245 m_num_per_line = 4;
246 break;
247 case 8:
248 m_num_per_line = 2;
249 break;
250 default:
251 m_num_per_line = 1;
252 break;
253 }
254 }
255 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000256 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000257 break;
258
259 case eFormatVectorOfChar:
260 case eFormatVectorOfSInt8:
261 case eFormatVectorOfUInt8:
262 case eFormatVectorOfSInt16:
263 case eFormatVectorOfUInt16:
264 case eFormatVectorOfSInt32:
265 case eFormatVectorOfUInt32:
266 case eFormatVectorOfSInt64:
267 case eFormatVectorOfUInt64:
268 case eFormatVectorOfFloat32:
269 case eFormatVectorOfFloat64:
270 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000271 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000272 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000273 if (!num_per_line_option_set)
274 m_num_per_line = 1;
275 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000276 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000277 break;
278 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000279 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000280 }
281
Greg Clayton82f4cf42011-10-26 04:32:38 +0000282 bool
283 AnyOptionWasSet () const
284 {
285 return m_num_per_line.OptionWasSet() ||
286 m_output_as_binary ||
287 m_view_as_type.OptionWasSet();
288 }
289
Greg Clayton84c39662011-04-27 22:04:39 +0000290 OptionValueUInt64 m_num_per_line;
291 bool m_output_as_binary;
292 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000293 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000294};
295
296
297
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000298//----------------------------------------------------------------------
299// Read memory from the inferior process
300//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000301class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000302{
303public:
304
Greg Claytona7015092010-09-18 01:14:36 +0000305 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000306 CommandObjectParsed (interpreter,
307 "memory read",
308 "Read from the memory of the process being debugged.",
309 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000310 eFlagRequiresTarget | eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000311 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000312 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000313 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000314 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000315 m_varobj_options(),
316 m_next_addr(LLDB_INVALID_ADDRESS),
317 m_prev_byte_size(0),
318 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
319 m_prev_memory_options (),
320 m_prev_outfile_options (),
321 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000322 {
Caroline Tice405fe672010-10-04 22:28:36 +0000323 CommandArgumentEntry arg1;
324 CommandArgumentEntry arg2;
325 CommandArgumentData start_addr_arg;
326 CommandArgumentData end_addr_arg;
327
328 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000329 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000330 start_addr_arg.arg_repetition = eArgRepeatPlain;
331
332 // There is only one variant this argument could be; put it into the argument entry.
333 arg1.push_back (start_addr_arg);
334
335 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000336 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000337 end_addr_arg.arg_repetition = eArgRepeatOptional;
338
339 // There is only one variant this argument could be; put it into the argument entry.
340 arg2.push_back (end_addr_arg);
341
342 // Push the data for the first argument into the m_arguments vector.
343 m_arguments.push_back (arg1);
344 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000345
Greg Clayton1deb7962011-10-25 06:44:01 +0000346 // Add the "--format" and "--count" options to group 1 and 3
347 m_option_group.Append (&m_format_options,
348 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000349 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000350 m_option_group.Append (&m_format_options,
351 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000352 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000353 // Add the "--size" option to group 1 and 2
354 m_option_group.Append (&m_format_options,
355 OptionGroupFormat::OPTION_GROUP_SIZE,
356 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000357 m_option_group.Append (&m_memory_options);
358 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton68ebae62011-04-28 20:55:26 +0000359 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000360 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000361 }
362
363 virtual
364 ~CommandObjectMemoryRead ()
365 {
366 }
367
368 Options *
369 GetOptions ()
370 {
Greg Clayton84c39662011-04-27 22:04:39 +0000371 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000372 }
373
Greg Clayton82f4cf42011-10-26 04:32:38 +0000374 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
375 {
376 return m_cmd_name.c_str();
377 }
378
Jim Ingham5a988412012-06-08 21:56:10 +0000379protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000381 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000382 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000383 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
384 Target *target = m_exe_ctx.GetTargetPtr();
385
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000386 const size_t argc = command.GetArgumentCount();
387
Greg Clayton82f4cf42011-10-26 04:32:38 +0000388 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000389 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000390 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
Greg Clayton2e1f7452012-12-15 02:08:17 +0000391 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392 result.SetStatus(eReturnStatusFailed);
393 return false;
394 }
395
Greg Clayton68ebae62011-04-28 20:55:26 +0000396 ClangASTType clang_ast_type;
397 Error error;
398
Greg Clayton84c39662011-04-27 22:04:39 +0000399 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
400 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000401 {
Greg Clayton84c39662011-04-27 22:04:39 +0000402 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000403
Greg Clayton84c39662011-04-27 22:04:39 +0000404 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000405 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000406 TypeList type_list;
407 uint32_t reference_count = 0;
408 uint32_t pointer_count = 0;
409 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000410
411#define ALL_KEYWORDS \
412 KEYWORD("const") \
413 KEYWORD("volatile") \
414 KEYWORD("restrict") \
415 KEYWORD("struct") \
416 KEYWORD("class") \
417 KEYWORD("union")
418
419#define KEYWORD(s) s,
420 static const char *g_keywords[] =
421 {
422 ALL_KEYWORDS
423 };
424#undef KEYWORD
425
426#define KEYWORD(s) (sizeof(s) - 1),
427 static const int g_keyword_lengths[] =
428 {
429 ALL_KEYWORDS
430 };
431#undef KEYWORD
432
433#undef ALL_KEYWORDS
434
435 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000436 std::string type_str(view_as_type_cstr);
437
438 // Remove all instances of g_keywords that are followed by spaces
439 for (size_t i = 0; i < g_num_keywords; ++i)
440 {
441 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000442 int keyword_len = g_keyword_lengths[i];
443
444 idx = 0;
445 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000446 {
447 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000448 {
Greg Clayton84c39662011-04-27 22:04:39 +0000449 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000450 idx = 0;
451 }
452 else
453 {
454 idx += keyword_len;
455 }
Greg Clayton84c39662011-04-27 22:04:39 +0000456 }
457 }
458 bool done = type_str.empty();
459 //
460 idx = type_str.find_first_not_of (" \t");
461 if (idx > 0 && idx != std::string::npos)
462 type_str.erase (0, idx);
463 while (!done)
464 {
465 // Strip trailing spaces
466 if (type_str.empty())
467 done = true;
468 else
469 {
470 switch (type_str[type_str.size()-1])
471 {
472 case '*':
473 ++pointer_count;
474 // fall through...
475 case ' ':
476 case '\t':
477 type_str.erase(type_str.size()-1);
478 break;
479
480 case '&':
481 if (reference_count == 0)
482 {
483 reference_count = 1;
484 type_str.erase(type_str.size()-1);
485 }
486 else
487 {
488 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
489 result.SetStatus(eReturnStatusFailed);
490 return false;
491 }
492 break;
493
494 default:
495 done = true;
496 break;
497 }
498 }
499 }
500
501 ConstString lookup_type_name(type_str.c_str());
Greg Claytonf9fc6092013-01-09 19:44:40 +0000502 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000503 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000504 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000505 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000506 if (sc.module_sp)
507 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000508 sc.module_sp->FindTypes (sc,
509 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000510 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000511 1,
512 type_list);
513 }
514 }
515 if (type_list.GetSize() == 0)
516 {
Greg Clayton29399a22012-04-06 17:41:13 +0000517 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000518 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000519 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000520 1,
521 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000522 }
523
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000524 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000525 {
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000526 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
527 if (tdecl)
528 {
529 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
530 }
Greg Clayton84c39662011-04-27 22:04:39 +0000531 }
532
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000533 if (clang_ast_type.IsValid() == false)
534 {
535 if (type_list.GetSize() == 0)
536 {
537 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
538 lookup_type_name.GetCString(),
539 view_as_type_cstr);
540 result.SetStatus(eReturnStatusFailed);
541 return false;
542 }
543 else
544 {
545 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton57ee3062013-07-11 22:46:58 +0000546 clang_ast_type = type_sp->GetClangFullType();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000547 }
548 }
Greg Clayton84c39662011-04-27 22:04:39 +0000549
550 while (pointer_count > 0)
551 {
Greg Clayton57ee3062013-07-11 22:46:58 +0000552 ClangASTType pointer_type = clang_ast_type.GetPointerType();
553 if (pointer_type.IsValid())
554 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000555 else
556 {
557 result.AppendError ("unable make a pointer type\n");
558 result.SetStatus(eReturnStatusFailed);
559 return false;
560 }
561 --pointer_count;
562 }
563
Greg Clayton57ee3062013-07-11 22:46:58 +0000564 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize();
Greg Clayton84c39662011-04-27 22:04:39 +0000565
Greg Clayton1deb7962011-10-25 06:44:01 +0000566 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000567 {
568 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
569 view_as_type_cstr);
570 result.SetStatus(eReturnStatusFailed);
571 return false;
572 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000573
Greg Clayton1deb7962011-10-25 06:44:01 +0000574 if (!m_format_options.GetCountValue().OptionWasSet())
575 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000576 }
577 else
578 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000579 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000580 }
581
582 // Look for invalid combinations of settings
583 if (error.Fail())
584 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000585 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000586 result.SetStatus(eReturnStatusFailed);
587 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000588 }
589
Greg Clayton82f4cf42011-10-26 04:32:38 +0000590 lldb::addr_t addr;
591 size_t total_byte_size = 0;
592 if (argc == 0)
593 {
594 // Use the last address and byte size and all options as they were
595 // if no options have been set
596 addr = m_next_addr;
597 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000598 clang_ast_type = m_prev_clang_ast_type;
599 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000600 !m_memory_options.AnyOptionWasSet() &&
601 !m_outfile_options.AnyOptionWasSet() &&
602 !m_varobj_options.AnyOptionWasSet())
603 {
604 m_format_options = m_prev_format_options;
605 m_memory_options = m_prev_memory_options;
606 m_outfile_options = m_prev_outfile_options;
607 m_varobj_options = m_prev_varobj_options;
608 }
609 }
610
Greg Clayton1deb7962011-10-25 06:44:01 +0000611 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000612 size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000613 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000614
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000615 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000616 {
617 total_byte_size = item_count * item_byte_size;
618 if (total_byte_size == 0)
619 total_byte_size = 32;
620 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000621
Greg Clayton82f4cf42011-10-26 04:32:38 +0000622 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000623 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000624
625 if (addr == LLDB_INVALID_ADDRESS)
626 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000627 result.AppendError("invalid start address expression.");
628 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000629 result.SetStatus(eReturnStatusFailed);
630 return false;
631 }
632
633 if (argc == 2)
634 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000635 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000636 if (end_addr == LLDB_INVALID_ADDRESS)
637 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000638 result.AppendError("invalid end address expression.");
639 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000640 result.SetStatus(eReturnStatusFailed);
641 return false;
642 }
643 else if (end_addr <= addr)
644 {
Daniel Malead01b2952012-11-29 21:49:15 +0000645 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000646 result.SetStatus(eReturnStatusFailed);
647 return false;
648 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000649 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000650 {
Daniel Malead01b2952012-11-29 21:49:15 +0000651 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000652 result.SetStatus(eReturnStatusFailed);
653 return false;
654 }
655
656 total_byte_size = end_addr - addr;
657 item_count = total_byte_size / item_byte_size;
658 }
Greg Clayton84c39662011-04-27 22:04:39 +0000659
Enrico Granatad325bf92013-06-04 22:54:16 +0000660 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
661
662 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000663 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000664 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
665 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
666 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
Sean Callanan1276c332012-04-28 01:27:38 +0000667 return false;
668 }
669
Greg Clayton84c39662011-04-27 22:04:39 +0000670 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000671 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000672 if (clang_ast_type.GetOpaqueQualType())
673 {
674 // Make sure we don't display our type as ASCII bytes like the default memory read
675 if (m_format_options.GetFormatValue().OptionWasSet() == false)
676 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
677
Greg Clayton57ee3062013-07-11 22:46:58 +0000678 bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000679 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000680 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000681 {
Greg Clayton84c39662011-04-27 22:04:39 +0000682 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000683 if (data_sp->GetBytes() == NULL)
684 {
685 result.AppendErrorWithFormat ("can't allocate 0x%zx bytes for the memory read buffer, specify a smaller size to read", total_byte_size);
686 result.SetStatus(eReturnStatusFailed);
687 return false;
688 }
689
Greg Claytone72dfb32012-02-24 01:59:29 +0000690 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000691 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000692 if (bytes_read == 0)
693 {
Greg Clayton57f06302012-05-25 17:05:55 +0000694 const char *error_cstr = error.AsCString();
695 if (error_cstr && error_cstr[0])
696 {
697 result.AppendError(error_cstr);
698 }
699 else
700 {
Daniel Malead01b2952012-11-29 21:49:15 +0000701 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000702 }
Greg Clayton84c39662011-04-27 22:04:39 +0000703 result.SetStatus(eReturnStatusFailed);
704 return false;
705 }
706
707 if (bytes_read < total_byte_size)
Jim Ingham9d8dd4b2013-01-25 23:05:01 +0000708 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000709 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000710 else
711 {
712 // we treat c-strings as a special case because they do not have a fixed size
713 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
714 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
715 else
716 item_byte_size = target->GetMaximumSizeOfStringSummary();
717 if (!m_format_options.GetCountValue().OptionWasSet())
718 item_count = 1;
719 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000720 if (data_sp->GetBytes() == NULL)
721 {
722 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));
723 result.SetStatus(eReturnStatusFailed);
724 return false;
725 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000726 uint8_t *data_ptr = data_sp->GetBytes();
727 auto data_addr = addr;
728 auto count = item_count;
729 item_count = 0;
730 while (item_count < count)
731 {
732 std::string buffer;
733 buffer.resize(item_byte_size+1,0);
734 Error error;
735 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
736 if (error.Fail())
737 {
738 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
739 result.SetStatus(eReturnStatusFailed);
740 return false;
741 }
742 if (item_byte_size == read)
743 {
744 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
745 break;
746 }
747 read+=1; // account for final NULL byte
748 memcpy(data_ptr, &buffer[0], read);
749 data_ptr += read;
750 data_addr += read;
751 bytes_read += read;
752 item_count++; // if we break early we know we only read item_count strings
753 }
754 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
755 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000756
Greg Clayton2e1f7452012-12-15 02:08:17 +0000757 m_next_addr = addr + bytes_read;
758 m_prev_byte_size = bytes_read;
759 m_prev_format_options = m_format_options;
760 m_prev_memory_options = m_memory_options;
761 m_prev_outfile_options = m_outfile_options;
762 m_prev_varobj_options = m_varobj_options;
763 m_prev_clang_ast_type = clang_ast_type;
764
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000765 StreamFile outfile_stream;
766 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000767 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
768 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000769 {
770 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000771 outfile_spec.GetPath (path, sizeof(path));
772
773 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
774 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
775 if (append)
776 open_options |= File::eOpenOptionAppend;
777
778 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000779 {
Greg Clayton84c39662011-04-27 22:04:39 +0000780 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000781 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000782 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000783 if (bytes_written > 0)
784 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000785 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000786 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000787 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000788 path);
789 return true;
790 }
791 else
792 {
Daniel Malead01b2952012-11-29 21:49:15 +0000793 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000794 result.SetStatus(eReturnStatusFailed);
795 return false;
796 }
797 }
798 else
799 {
800 // We are going to write ASCII to the file just point the
801 // output_stream to our outfile_stream...
802 output_stream = &outfile_stream;
803 }
804 }
805 else
806 {
Greg Clayton84c39662011-04-27 22:04:39 +0000807 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000808 result.SetStatus(eReturnStatusFailed);
809 return false;
810 }
811 }
812 else
813 {
814 output_stream = &result.GetOutputStream();
815 }
816
Greg Clayton84c39662011-04-27 22:04:39 +0000817
Greg Claytonf9fc6092013-01-09 19:44:40 +0000818 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000819 if (clang_ast_type.GetOpaqueQualType())
820 {
821 for (uint32_t i = 0; i<item_count; ++i)
822 {
823 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000824 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000825 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000826 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000827 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000828 name_strm.GetString().c_str(),
829 address,
830 clang_ast_type));
831 if (valobj_sp)
832 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000833 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000834 if (format != eFormatDefault)
835 valobj_sp->SetFormat (format);
836
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000837 ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format));
838
Greg Clayton84c39662011-04-27 22:04:39 +0000839 ValueObject::DumpValueObject (*output_stream,
840 valobj_sp.get(),
Enrico Granata0c489f52012-03-01 04:24:26 +0000841 options);
Greg Clayton84c39662011-04-27 22:04:39 +0000842 }
843 else
844 {
845 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
846 view_as_type_cstr,
847 name_strm.GetString().c_str());
848 result.SetStatus(eReturnStatusFailed);
849 return false;
850 }
851 }
852 return true;
853 }
854
855 result.SetStatus(eReturnStatusSuccessFinishResult);
856 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000857 target->GetArchitecture().GetByteOrder(),
858 target->GetArchitecture().GetAddressByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000859
860 Format format = m_format_options.GetFormat();
861 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
862 && (item_byte_size != 1)
863 && (item_count == 1))
864 {
865 // this turns requests such as
866 // memory read -fc -s10 -c1 *charPtrPtr
867 // which make no sense (what is a char of size 10?)
868 // into a request for fetching 10 chars of size 1 from the same memory location
869 format = eFormatCharArray;
870 item_count = item_byte_size;
871 item_byte_size = 1;
872 }
Greg Clayton84c39662011-04-27 22:04:39 +0000873
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000874 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000875 size_t bytes_dumped = data.Dump (output_stream,
876 0,
Enrico Granata31898912013-05-21 17:39:04 +0000877 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000878 item_byte_size,
879 item_count,
880 num_per_line,
881 addr,
882 0,
883 0,
884 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000885 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000886 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000887 return true;
888 }
889
Greg Clayton84c39662011-04-27 22:04:39 +0000890 OptionGroupOptions m_option_group;
891 OptionGroupFormat m_format_options;
892 OptionGroupReadMemory m_memory_options;
893 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000894 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000895 lldb::addr_t m_next_addr;
896 lldb::addr_t m_prev_byte_size;
897 OptionGroupFormat m_prev_format_options;
898 OptionGroupReadMemory m_prev_memory_options;
899 OptionGroupOutputFile m_prev_outfile_options;
900 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000901 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000902};
903
Greg Clayton1deb7962011-10-25 06:44:01 +0000904
905OptionDefinition
906g_memory_write_option_table[] =
907{
908{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
909{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
910};
911
912
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000913//----------------------------------------------------------------------
914// Write memory to the inferior process
915//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000916class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000917{
918public:
919
Greg Clayton1deb7962011-10-25 06:44:01 +0000920 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000921 {
922 public:
Greg Clayton1deb7962011-10-25 06:44:01 +0000923 OptionGroupWriteMemory () :
924 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000925 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000926 }
927
928 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +0000929 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000930 {
931 }
932
Greg Clayton1deb7962011-10-25 06:44:01 +0000933 virtual uint32_t
934 GetNumDefinitions ()
935 {
936 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
937 }
938
939 virtual const OptionDefinition*
940 GetDefinitions ()
941 {
942 return g_memory_write_option_table;
943 }
944
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000945 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000946 SetOptionValue (CommandInterpreter &interpreter,
947 uint32_t option_idx,
948 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000949 {
950 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000951 const int short_option = g_memory_write_option_table[option_idx].short_option;
Greg Clayton1deb7962011-10-25 06:44:01 +0000952
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000953 switch (short_option)
954 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000955 case 'i':
956 m_infile.SetFile (option_arg, true);
957 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000958 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000959 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +0000960 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000961 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000962 break;
963
964 case 'o':
965 {
966 bool success;
967 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
968 if (!success)
969 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000970 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +0000971 }
972 }
973 break;
974
975 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000976 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +0000977 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000978 }
979 return error;
980 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000981
982 virtual void
983 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000984 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000985 m_infile.Clear();
986 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000987 }
988
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000989 FileSpec m_infile;
990 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000991 };
992
Greg Claytona7015092010-09-18 01:14:36 +0000993 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000994 CommandObjectParsed (interpreter,
995 "memory write",
996 "Write to the memory of the process being debugged.",
997 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000998 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +0000999 m_option_group (interpreter),
1000 m_format_options (eFormatBytes, 1, UINT64_MAX),
1001 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001002 {
Caroline Tice405fe672010-10-04 22:28:36 +00001003 CommandArgumentEntry arg1;
1004 CommandArgumentEntry arg2;
1005 CommandArgumentData addr_arg;
1006 CommandArgumentData value_arg;
1007
1008 // Define the first (and only) variant of this arg.
1009 addr_arg.arg_type = eArgTypeAddress;
1010 addr_arg.arg_repetition = eArgRepeatPlain;
1011
1012 // There is only one variant this argument could be; put it into the argument entry.
1013 arg1.push_back (addr_arg);
1014
1015 // Define the first (and only) variant of this arg.
1016 value_arg.arg_type = eArgTypeValue;
1017 value_arg.arg_repetition = eArgRepeatPlus;
1018
1019 // There is only one variant this argument could be; put it into the argument entry.
1020 arg2.push_back (value_arg);
1021
1022 // Push the data for the first argument into the m_arguments vector.
1023 m_arguments.push_back (arg1);
1024 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001025
1026 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1027 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1028 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1029 m_option_group.Finalize();
1030
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001031 }
1032
1033 virtual
1034 ~CommandObjectMemoryWrite ()
1035 {
1036 }
1037
1038 Options *
1039 GetOptions ()
1040 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001041 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001042 }
1043
1044 bool
1045 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1046 {
1047 if (total_byte_size > 8)
1048 return false;
1049
1050 if (total_byte_size == 8)
1051 return true;
1052
1053 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1054 return uval64 <= max;
1055 }
1056
1057 bool
1058 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1059 {
1060 if (total_byte_size > 8)
1061 return false;
1062
1063 if (total_byte_size == 8)
1064 return true;
1065
1066 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1067 const int64_t min = ~(max);
1068 return min <= sval64 && sval64 <= max;
1069 }
1070
Jim Ingham5a988412012-06-08 21:56:10 +00001071protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001072 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001073 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001074 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001075 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1076 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001077
1078 const size_t argc = command.GetArgumentCount();
1079
Greg Clayton1deb7962011-10-25 06:44:01 +00001080 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001081 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001082 if (argc < 1)
1083 {
1084 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1085 result.SetStatus(eReturnStatusFailed);
1086 return false;
1087 }
1088 }
1089 else if (argc < 2)
1090 {
1091 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 +00001092 result.SetStatus(eReturnStatusFailed);
1093 return false;
1094 }
1095
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001096 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001097 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1098 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001099
Greg Clayton1deb7962011-10-25 06:44:01 +00001100 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1101 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001102
Greg Claytonb9d5df52012-12-06 22:49:16 +00001103 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001104 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001105 command.GetArgumentAtIndex(0),
1106 LLDB_INVALID_ADDRESS,
1107 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001108
1109 if (addr == LLDB_INVALID_ADDRESS)
1110 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001111 result.AppendError("invalid address expression\n");
1112 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001113 result.SetStatus(eReturnStatusFailed);
1114 return false;
1115 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001116
Greg Clayton1deb7962011-10-25 06:44:01 +00001117 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001118 {
1119 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +00001120 if (item_byte_size > 0)
1121 length = item_byte_size;
1122 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001123 if (data_sp)
1124 {
1125 length = data_sp->GetByteSize();
1126 if (length > 0)
1127 {
1128 Error error;
1129 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1130
1131 if (bytes_written == length)
1132 {
1133 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001134 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001135 result.SetStatus(eReturnStatusSuccessFinishResult);
1136 }
1137 else if (bytes_written > 0)
1138 {
1139 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001140 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 +00001141 result.SetStatus(eReturnStatusSuccessFinishResult);
1142 }
1143 else
1144 {
Daniel Malead01b2952012-11-29 21:49:15 +00001145 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001146 result.SetStatus(eReturnStatusFailed);
1147 }
1148 }
1149 }
1150 else
1151 {
1152 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1153 result.SetStatus(eReturnStatusFailed);
1154 }
1155 return result.Succeeded();
1156 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001157 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001158 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001159 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001160 item_byte_size = buffer.GetAddressByteSize();
1161 else
1162 item_byte_size = 1;
1163 }
1164
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001165 command.Shift(); // shift off the address argument
1166 uint64_t uval64;
1167 int64_t sval64;
1168 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001169 const size_t num_value_args = command.GetArgumentCount();
1170 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001171 {
1172 const char *value_str = command.GetArgumentAtIndex(i);
1173
Greg Clayton1deb7962011-10-25 06:44:01 +00001174 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001175 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001176 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001177 case eFormatFloat: // TODO: add support for floats soon
1178 case eFormatCharPrintable:
1179 case eFormatBytesWithASCII:
1180 case eFormatComplex:
1181 case eFormatEnum:
1182 case eFormatUnicode16:
1183 case eFormatUnicode32:
1184 case eFormatVectorOfChar:
1185 case eFormatVectorOfSInt8:
1186 case eFormatVectorOfUInt8:
1187 case eFormatVectorOfSInt16:
1188 case eFormatVectorOfUInt16:
1189 case eFormatVectorOfSInt32:
1190 case eFormatVectorOfUInt32:
1191 case eFormatVectorOfSInt64:
1192 case eFormatVectorOfUInt64:
1193 case eFormatVectorOfFloat32:
1194 case eFormatVectorOfFloat64:
1195 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001196 case eFormatOSType:
1197 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001198 case eFormatAddressInfo:
1199 case eFormatHexFloat:
1200 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001201 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001202 result.AppendError("unsupported format for writing memory");
1203 result.SetStatus(eReturnStatusFailed);
1204 return false;
1205
1206 case eFormatDefault:
1207 case eFormatBytes:
1208 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001209 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001210 case eFormatPointer:
1211
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001212 // Decode hex bytes
1213 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1214 if (!success)
1215 {
1216 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1217 result.SetStatus(eReturnStatusFailed);
1218 return false;
1219 }
1220 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1221 {
Daniel Malead01b2952012-11-29 21:49:15 +00001222 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001223 result.SetStatus(eReturnStatusFailed);
1224 return false;
1225 }
1226 buffer.PutMaxHex64 (uval64, item_byte_size);
1227 break;
1228
1229 case eFormatBoolean:
1230 uval64 = Args::StringToBoolean(value_str, false, &success);
1231 if (!success)
1232 {
1233 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1234 result.SetStatus(eReturnStatusFailed);
1235 return false;
1236 }
1237 buffer.PutMaxHex64 (uval64, item_byte_size);
1238 break;
1239
1240 case eFormatBinary:
1241 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1242 if (!success)
1243 {
1244 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1245 result.SetStatus(eReturnStatusFailed);
1246 return false;
1247 }
1248 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1249 {
Daniel Malead01b2952012-11-29 21:49:15 +00001250 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001251 result.SetStatus(eReturnStatusFailed);
1252 return false;
1253 }
1254 buffer.PutMaxHex64 (uval64, item_byte_size);
1255 break;
1256
Greg Clayton4e4294b2011-06-17 23:50:44 +00001257 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001258 case eFormatChar:
1259 case eFormatCString:
1260 if (value_str[0])
1261 {
1262 size_t len = strlen (value_str);
1263 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001264 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001265 ++len;
1266 Error error;
1267 if (process->WriteMemory (addr, value_str, len, error) == len)
1268 {
1269 addr += len;
1270 }
1271 else
1272 {
Daniel Malead01b2952012-11-29 21:49:15 +00001273 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001274 result.SetStatus(eReturnStatusFailed);
1275 return false;
1276 }
1277 }
1278 break;
1279
1280 case eFormatDecimal:
1281 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1282 if (!success)
1283 {
1284 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1285 result.SetStatus(eReturnStatusFailed);
1286 return false;
1287 }
1288 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1289 {
Daniel Malead01b2952012-11-29 21:49:15 +00001290 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001291 result.SetStatus(eReturnStatusFailed);
1292 return false;
1293 }
1294 buffer.PutMaxHex64 (sval64, item_byte_size);
1295 break;
1296
1297 case eFormatUnsigned:
1298 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1299 if (!success)
1300 {
1301 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1302 result.SetStatus(eReturnStatusFailed);
1303 return false;
1304 }
1305 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1306 {
Daniel Malead01b2952012-11-29 21:49:15 +00001307 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001308 result.SetStatus(eReturnStatusFailed);
1309 return false;
1310 }
1311 buffer.PutMaxHex64 (uval64, item_byte_size);
1312 break;
1313
1314 case eFormatOctal:
1315 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1316 if (!success)
1317 {
1318 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1319 result.SetStatus(eReturnStatusFailed);
1320 return false;
1321 }
1322 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1323 {
Daniel Malead01b2952012-11-29 21:49:15 +00001324 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001325 result.SetStatus(eReturnStatusFailed);
1326 return false;
1327 }
1328 buffer.PutMaxHex64 (uval64, item_byte_size);
1329 break;
1330 }
1331 }
1332
1333 if (!buffer.GetString().empty())
1334 {
1335 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001336 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001337 return true;
1338 else
1339 {
Daniel Malead01b2952012-11-29 21:49:15 +00001340 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001341 result.SetStatus(eReturnStatusFailed);
1342 return false;
1343 }
1344 }
1345 return true;
1346 }
1347
Greg Clayton1deb7962011-10-25 06:44:01 +00001348 OptionGroupOptions m_option_group;
1349 OptionGroupFormat m_format_options;
1350 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001351};
1352
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001353
1354//-------------------------------------------------------------------------
1355// CommandObjectMemory
1356//-------------------------------------------------------------------------
1357
Greg Clayton66111032010-06-23 01:19:29 +00001358CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001359 CommandObjectMultiword (interpreter,
1360 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001361 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001362 "memory <subcommand> [<subcommand-options>]")
1363{
Greg Claytona7015092010-09-18 01:14:36 +00001364 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1365 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001366}
1367
1368CommandObjectMemory::~CommandObjectMemory ()
1369{
1370}