blob: fabbfbbf3fc7816b1ee47921f3839278bbdd1e81 [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
Virgile Bellobdae3782013-08-28 12:14:27 +000015#include <inttypes.h>
16
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017// C++ Includes
18// Other libraries and framework includes
19// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Core/DataBufferHeap.h"
21#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000022#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000023#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000025#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton66111032010-06-23 01:19:29 +000026#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000028#include "lldb/Interpreter/CommandInterpreter.h"
29#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000030#include "lldb/Interpreter/OptionGroupFormat.h"
31#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000032#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000033#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton1f746072012-08-29 21:13:06 +000034#include "lldb/Symbol/TypeList.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035#include "lldb/Target/Process.h"
Greg Clayton84c39662011-04-27 22:04:39 +000036#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037
38using namespace lldb;
39using namespace lldb_private;
40
Greg Clayton68ebae62011-04-28 20:55:26 +000041static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000042g_option_table[] =
43{
Greg Clayton84c39662011-04-27 22:04:39 +000044 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
45 { 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 +000046 { 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 +000047 { LLDB_OPT_SET_1|
48 LLDB_OPT_SET_2|
Enrico Granatad325bf92013-06-04 22:54:16 +000049 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 +000050};
51
52
53
54class OptionGroupReadMemory : public OptionGroup
55{
56public:
57
58 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000059 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000060 m_output_as_binary (false),
61 m_view_as_type()
62 {
63 }
64
65 virtual
66 ~OptionGroupReadMemory ()
67 {
68 }
69
70
71 virtual uint32_t
72 GetNumDefinitions ()
73 {
74 return sizeof (g_option_table) / sizeof (OptionDefinition);
75 }
76
77 virtual const OptionDefinition*
78 GetDefinitions ()
79 {
80 return g_option_table;
81 }
82
83 virtual Error
84 SetOptionValue (CommandInterpreter &interpreter,
85 uint32_t option_idx,
86 const char *option_arg)
87 {
88 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000089 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000090
91 switch (short_option)
92 {
93 case 'l':
94 error = m_num_per_line.SetValueFromCString (option_arg);
95 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +000096 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +000097 break;
Greg Clayton1deb7962011-10-25 06:44:01 +000098
Greg Clayton84c39662011-04-27 22:04:39 +000099 case 'b':
100 m_output_as_binary = true;
101 break;
102
103 case 't':
104 error = m_view_as_type.SetValueFromCString (option_arg);
105 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000106
107 case 'r':
108 m_force = true;
109 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000110
111 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000112 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000113 break;
114 }
115 return error;
116 }
117
118 virtual void
119 OptionParsingStarting (CommandInterpreter &interpreter)
120 {
Greg Clayton84c39662011-04-27 22:04:39 +0000121 m_num_per_line.Clear();
122 m_output_as_binary = false;
123 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000124 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000125 }
126
Greg Clayton68ebae62011-04-28 20:55:26 +0000127 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000128 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000129 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000130 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000131 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
132 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000133 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000134 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000135 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000136
Greg Clayton68ebae62011-04-28 20:55:26 +0000137 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000138 {
139 default:
140 break;
141
142 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000143 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000144 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000145 if (!num_per_line_option_set)
146 m_num_per_line = 1;
147 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000148 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000149 break;
150
151 case eFormatCString:
152 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000153
154 case eFormatInstruction:
155 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000156 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000157 m_num_per_line = 1;
158 break;
159
160 case eFormatAddressInfo:
161 if (!byte_size_option_set)
162 byte_size_value = target->GetArchitecture().GetAddressByteSize();
163 m_num_per_line = 1;
164 if (!count_option_set)
165 format_options.GetCountValue() = 8;
166 break;
167
Greg Clayton84c39662011-04-27 22:04:39 +0000168 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000169 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000170 if (!num_per_line_option_set)
171 m_num_per_line = 4;
172 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000173 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000174 break;
175
176 case eFormatBinary:
177 case eFormatFloat:
178 case eFormatOctal:
179 case eFormatDecimal:
180 case eFormatEnum:
181 case eFormatUnicode16:
182 case eFormatUnicode32:
183 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000184 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000185 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000186 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000187 if (!num_per_line_option_set)
188 m_num_per_line = 1;
189 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000190 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000191 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000192
Greg Clayton84c39662011-04-27 22:04:39 +0000193 case eFormatBytes:
194 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000195 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000196 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000197 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000198 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000199 "\tconsider using a different display format or don't specify the byte size",
200 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000201 }
202 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000203 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000204 if (!num_per_line_option_set)
205 m_num_per_line = 16;
206 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000207 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000208 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000209 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000210 case eFormatChar:
211 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000212 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000213 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000214 if (!num_per_line_option_set)
215 m_num_per_line = 32;
216 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000217 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000218 break;
219 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000220 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000221 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000222 if (!num_per_line_option_set)
223 m_num_per_line = 1;
224 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000225 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000226 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000227 case eFormatComplexInteger:
228 if (!byte_size_option_set)
229 byte_size_value = 8;
230 if (!num_per_line_option_set)
231 m_num_per_line = 1;
232 if (!count_option_set)
233 format_options.GetCountValue() = 8;
234 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000235 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000236 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000237 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000238 if (!num_per_line_option_set)
239 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000240 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000241 {
242 case 1:
243 case 2:
244 m_num_per_line = 8;
245 break;
246 case 4:
247 m_num_per_line = 4;
248 break;
249 case 8:
250 m_num_per_line = 2;
251 break;
252 default:
253 m_num_per_line = 1;
254 break;
255 }
256 }
257 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000258 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000259 break;
260
261 case eFormatVectorOfChar:
262 case eFormatVectorOfSInt8:
263 case eFormatVectorOfUInt8:
264 case eFormatVectorOfSInt16:
265 case eFormatVectorOfUInt16:
266 case eFormatVectorOfSInt32:
267 case eFormatVectorOfUInt32:
268 case eFormatVectorOfSInt64:
269 case eFormatVectorOfUInt64:
270 case eFormatVectorOfFloat32:
271 case eFormatVectorOfFloat64:
272 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000273 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000274 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000275 if (!num_per_line_option_set)
276 m_num_per_line = 1;
277 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000278 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000279 break;
280 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000281 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000282 }
283
Greg Clayton82f4cf42011-10-26 04:32:38 +0000284 bool
285 AnyOptionWasSet () const
286 {
287 return m_num_per_line.OptionWasSet() ||
288 m_output_as_binary ||
289 m_view_as_type.OptionWasSet();
290 }
291
Greg Clayton84c39662011-04-27 22:04:39 +0000292 OptionValueUInt64 m_num_per_line;
293 bool m_output_as_binary;
294 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000295 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000296};
297
298
299
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300//----------------------------------------------------------------------
301// Read memory from the inferior process
302//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000303class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000304{
305public:
306
Greg Claytona7015092010-09-18 01:14:36 +0000307 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000308 CommandObjectParsed (interpreter,
309 "memory read",
310 "Read from the memory of the process being debugged.",
311 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000312 eFlagRequiresTarget | eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000313 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000314 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000315 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000316 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000317 m_varobj_options(),
318 m_next_addr(LLDB_INVALID_ADDRESS),
319 m_prev_byte_size(0),
320 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
321 m_prev_memory_options (),
322 m_prev_outfile_options (),
323 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000324 {
Caroline Tice405fe672010-10-04 22:28:36 +0000325 CommandArgumentEntry arg1;
326 CommandArgumentEntry arg2;
327 CommandArgumentData start_addr_arg;
328 CommandArgumentData end_addr_arg;
329
330 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000331 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000332 start_addr_arg.arg_repetition = eArgRepeatPlain;
333
334 // There is only one variant this argument could be; put it into the argument entry.
335 arg1.push_back (start_addr_arg);
336
337 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000338 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000339 end_addr_arg.arg_repetition = eArgRepeatOptional;
340
341 // There is only one variant this argument could be; put it into the argument entry.
342 arg2.push_back (end_addr_arg);
343
344 // Push the data for the first argument into the m_arguments vector.
345 m_arguments.push_back (arg1);
346 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000347
Greg Clayton1deb7962011-10-25 06:44:01 +0000348 // Add the "--format" and "--count" options to group 1 and 3
349 m_option_group.Append (&m_format_options,
350 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000351 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000352 m_option_group.Append (&m_format_options,
353 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000354 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000355 // Add the "--size" option to group 1 and 2
356 m_option_group.Append (&m_format_options,
357 OptionGroupFormat::OPTION_GROUP_SIZE,
358 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000359 m_option_group.Append (&m_memory_options);
360 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 +0000361 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000362 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000363 }
364
365 virtual
366 ~CommandObjectMemoryRead ()
367 {
368 }
369
370 Options *
371 GetOptions ()
372 {
Greg Clayton84c39662011-04-27 22:04:39 +0000373 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000374 }
375
Greg Clayton82f4cf42011-10-26 04:32:38 +0000376 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
377 {
378 return m_cmd_name.c_str();
379 }
380
Jim Ingham5a988412012-06-08 21:56:10 +0000381protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000382 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000383 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000385 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
386 Target *target = m_exe_ctx.GetTargetPtr();
387
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388 const size_t argc = command.GetArgumentCount();
389
Greg Clayton82f4cf42011-10-26 04:32:38 +0000390 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000391 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000392 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 +0000393 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000394 result.SetStatus(eReturnStatusFailed);
395 return false;
396 }
397
Greg Clayton68ebae62011-04-28 20:55:26 +0000398 ClangASTType clang_ast_type;
399 Error error;
400
Greg Clayton84c39662011-04-27 22:04:39 +0000401 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
402 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000403 {
Greg Clayton84c39662011-04-27 22:04:39 +0000404 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000405
Greg Clayton84c39662011-04-27 22:04:39 +0000406 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000407 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000408 TypeList type_list;
409 uint32_t reference_count = 0;
410 uint32_t pointer_count = 0;
411 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000412
413#define ALL_KEYWORDS \
414 KEYWORD("const") \
415 KEYWORD("volatile") \
416 KEYWORD("restrict") \
417 KEYWORD("struct") \
418 KEYWORD("class") \
419 KEYWORD("union")
420
421#define KEYWORD(s) s,
422 static const char *g_keywords[] =
423 {
424 ALL_KEYWORDS
425 };
426#undef KEYWORD
427
428#define KEYWORD(s) (sizeof(s) - 1),
429 static const int g_keyword_lengths[] =
430 {
431 ALL_KEYWORDS
432 };
433#undef KEYWORD
434
435#undef ALL_KEYWORDS
436
437 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000438 std::string type_str(view_as_type_cstr);
439
440 // Remove all instances of g_keywords that are followed by spaces
441 for (size_t i = 0; i < g_num_keywords; ++i)
442 {
443 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000444 int keyword_len = g_keyword_lengths[i];
445
446 idx = 0;
447 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000448 {
449 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000450 {
Greg Clayton84c39662011-04-27 22:04:39 +0000451 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000452 idx = 0;
453 }
454 else
455 {
456 idx += keyword_len;
457 }
Greg Clayton84c39662011-04-27 22:04:39 +0000458 }
459 }
460 bool done = type_str.empty();
461 //
462 idx = type_str.find_first_not_of (" \t");
463 if (idx > 0 && idx != std::string::npos)
464 type_str.erase (0, idx);
465 while (!done)
466 {
467 // Strip trailing spaces
468 if (type_str.empty())
469 done = true;
470 else
471 {
472 switch (type_str[type_str.size()-1])
473 {
474 case '*':
475 ++pointer_count;
476 // fall through...
477 case ' ':
478 case '\t':
479 type_str.erase(type_str.size()-1);
480 break;
481
482 case '&':
483 if (reference_count == 0)
484 {
485 reference_count = 1;
486 type_str.erase(type_str.size()-1);
487 }
488 else
489 {
490 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
491 result.SetStatus(eReturnStatusFailed);
492 return false;
493 }
494 break;
495
496 default:
497 done = true;
498 break;
499 }
500 }
501 }
502
503 ConstString lookup_type_name(type_str.c_str());
Greg Claytonf9fc6092013-01-09 19:44:40 +0000504 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000505 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000506 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000507 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000508 if (sc.module_sp)
509 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000510 sc.module_sp->FindTypes (sc,
511 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000512 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000513 1,
514 type_list);
515 }
516 }
517 if (type_list.GetSize() == 0)
518 {
Greg Clayton29399a22012-04-06 17:41:13 +0000519 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000520 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000521 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000522 1,
523 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000524 }
525
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000526 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000527 {
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000528 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
529 if (tdecl)
530 {
531 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
532 }
Greg Clayton84c39662011-04-27 22:04:39 +0000533 }
534
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000535 if (clang_ast_type.IsValid() == false)
536 {
537 if (type_list.GetSize() == 0)
538 {
539 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
540 lookup_type_name.GetCString(),
541 view_as_type_cstr);
542 result.SetStatus(eReturnStatusFailed);
543 return false;
544 }
545 else
546 {
547 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton57ee3062013-07-11 22:46:58 +0000548 clang_ast_type = type_sp->GetClangFullType();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000549 }
550 }
Greg Clayton84c39662011-04-27 22:04:39 +0000551
552 while (pointer_count > 0)
553 {
Greg Clayton57ee3062013-07-11 22:46:58 +0000554 ClangASTType pointer_type = clang_ast_type.GetPointerType();
555 if (pointer_type.IsValid())
556 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000557 else
558 {
559 result.AppendError ("unable make a pointer type\n");
560 result.SetStatus(eReturnStatusFailed);
561 return false;
562 }
563 --pointer_count;
564 }
565
Greg Clayton57ee3062013-07-11 22:46:58 +0000566 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize();
Greg Clayton84c39662011-04-27 22:04:39 +0000567
Greg Clayton1deb7962011-10-25 06:44:01 +0000568 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000569 {
570 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
571 view_as_type_cstr);
572 result.SetStatus(eReturnStatusFailed);
573 return false;
574 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000575
Greg Clayton1deb7962011-10-25 06:44:01 +0000576 if (!m_format_options.GetCountValue().OptionWasSet())
577 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000578 }
579 else
580 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000581 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000582 }
583
584 // Look for invalid combinations of settings
585 if (error.Fail())
586 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000587 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000588 result.SetStatus(eReturnStatusFailed);
589 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000590 }
591
Greg Clayton82f4cf42011-10-26 04:32:38 +0000592 lldb::addr_t addr;
593 size_t total_byte_size = 0;
594 if (argc == 0)
595 {
596 // Use the last address and byte size and all options as they were
597 // if no options have been set
598 addr = m_next_addr;
599 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000600 clang_ast_type = m_prev_clang_ast_type;
601 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000602 !m_memory_options.AnyOptionWasSet() &&
603 !m_outfile_options.AnyOptionWasSet() &&
604 !m_varobj_options.AnyOptionWasSet())
605 {
606 m_format_options = m_prev_format_options;
607 m_memory_options = m_prev_memory_options;
608 m_outfile_options = m_prev_outfile_options;
609 m_varobj_options = m_prev_varobj_options;
610 }
611 }
612
Greg Clayton1deb7962011-10-25 06:44:01 +0000613 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000614 size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000615 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000616
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000617 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000618 {
619 total_byte_size = item_count * item_byte_size;
620 if (total_byte_size == 0)
621 total_byte_size = 32;
622 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000623
Greg Clayton82f4cf42011-10-26 04:32:38 +0000624 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000625 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000626
627 if (addr == LLDB_INVALID_ADDRESS)
628 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000629 result.AppendError("invalid start address expression.");
630 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000631 result.SetStatus(eReturnStatusFailed);
632 return false;
633 }
634
635 if (argc == 2)
636 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000637 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000638 if (end_addr == LLDB_INVALID_ADDRESS)
639 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000640 result.AppendError("invalid end address expression.");
641 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000642 result.SetStatus(eReturnStatusFailed);
643 return false;
644 }
645 else if (end_addr <= addr)
646 {
Daniel Malead01b2952012-11-29 21:49:15 +0000647 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 +0000648 result.SetStatus(eReturnStatusFailed);
649 return false;
650 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000651 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000652 {
Daniel Malead01b2952012-11-29 21:49:15 +0000653 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 +0000654 result.SetStatus(eReturnStatusFailed);
655 return false;
656 }
657
658 total_byte_size = end_addr - addr;
659 item_count = total_byte_size / item_byte_size;
660 }
Greg Clayton84c39662011-04-27 22:04:39 +0000661
Enrico Granatad325bf92013-06-04 22:54:16 +0000662 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
663
664 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000665 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000666 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
667 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
668 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 +0000669 return false;
670 }
671
Greg Clayton84c39662011-04-27 22:04:39 +0000672 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000673 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000674 if (clang_ast_type.GetOpaqueQualType())
675 {
676 // Make sure we don't display our type as ASCII bytes like the default memory read
677 if (m_format_options.GetFormatValue().OptionWasSet() == false)
678 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
679
Greg Clayton57ee3062013-07-11 22:46:58 +0000680 bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000681 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000682 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000683 {
Greg Clayton84c39662011-04-27 22:04:39 +0000684 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000685 if (data_sp->GetBytes() == NULL)
686 {
687 result.AppendErrorWithFormat ("can't allocate 0x%zx bytes for the memory read buffer, specify a smaller size to read", total_byte_size);
688 result.SetStatus(eReturnStatusFailed);
689 return false;
690 }
691
Greg Claytone72dfb32012-02-24 01:59:29 +0000692 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000693 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000694 if (bytes_read == 0)
695 {
Greg Clayton57f06302012-05-25 17:05:55 +0000696 const char *error_cstr = error.AsCString();
697 if (error_cstr && error_cstr[0])
698 {
699 result.AppendError(error_cstr);
700 }
701 else
702 {
Daniel Malead01b2952012-11-29 21:49:15 +0000703 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000704 }
Greg Clayton84c39662011-04-27 22:04:39 +0000705 result.SetStatus(eReturnStatusFailed);
706 return false;
707 }
708
709 if (bytes_read < total_byte_size)
Jim Ingham9d8dd4b2013-01-25 23:05:01 +0000710 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 +0000711 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000712 else
713 {
714 // we treat c-strings as a special case because they do not have a fixed size
715 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
716 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
717 else
718 item_byte_size = target->GetMaximumSizeOfStringSummary();
719 if (!m_format_options.GetCountValue().OptionWasSet())
720 item_count = 1;
721 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000722 if (data_sp->GetBytes() == NULL)
723 {
724 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));
725 result.SetStatus(eReturnStatusFailed);
726 return false;
727 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000728 uint8_t *data_ptr = data_sp->GetBytes();
729 auto data_addr = addr;
730 auto count = item_count;
731 item_count = 0;
732 while (item_count < count)
733 {
734 std::string buffer;
735 buffer.resize(item_byte_size+1,0);
736 Error error;
737 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
738 if (error.Fail())
739 {
740 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
741 result.SetStatus(eReturnStatusFailed);
742 return false;
743 }
744 if (item_byte_size == read)
745 {
746 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
747 break;
748 }
749 read+=1; // account for final NULL byte
750 memcpy(data_ptr, &buffer[0], read);
751 data_ptr += read;
752 data_addr += read;
753 bytes_read += read;
754 item_count++; // if we break early we know we only read item_count strings
755 }
756 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
757 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000758
Greg Clayton2e1f7452012-12-15 02:08:17 +0000759 m_next_addr = addr + bytes_read;
760 m_prev_byte_size = bytes_read;
761 m_prev_format_options = m_format_options;
762 m_prev_memory_options = m_memory_options;
763 m_prev_outfile_options = m_outfile_options;
764 m_prev_varobj_options = m_varobj_options;
765 m_prev_clang_ast_type = clang_ast_type;
766
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000767 StreamFile outfile_stream;
768 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000769 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
770 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000771 {
772 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000773 outfile_spec.GetPath (path, sizeof(path));
774
775 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
776 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
777 if (append)
778 open_options |= File::eOpenOptionAppend;
779
780 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000781 {
Greg Clayton84c39662011-04-27 22:04:39 +0000782 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000783 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000784 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000785 if (bytes_written > 0)
786 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000787 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000788 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000789 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000790 path);
791 return true;
792 }
793 else
794 {
Daniel Malead01b2952012-11-29 21:49:15 +0000795 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000796 result.SetStatus(eReturnStatusFailed);
797 return false;
798 }
799 }
800 else
801 {
802 // We are going to write ASCII to the file just point the
803 // output_stream to our outfile_stream...
804 output_stream = &outfile_stream;
805 }
806 }
807 else
808 {
Greg Clayton84c39662011-04-27 22:04:39 +0000809 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000810 result.SetStatus(eReturnStatusFailed);
811 return false;
812 }
813 }
814 else
815 {
816 output_stream = &result.GetOutputStream();
817 }
818
Greg Clayton84c39662011-04-27 22:04:39 +0000819
Greg Claytonf9fc6092013-01-09 19:44:40 +0000820 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000821 if (clang_ast_type.GetOpaqueQualType())
822 {
823 for (uint32_t i = 0; i<item_count; ++i)
824 {
825 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000826 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000827 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000828 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000829 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000830 name_strm.GetString().c_str(),
831 address,
832 clang_ast_type));
833 if (valobj_sp)
834 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000835 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000836 if (format != eFormatDefault)
837 valobj_sp->SetFormat (format);
838
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000839 ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format));
840
Greg Clayton84c39662011-04-27 22:04:39 +0000841 ValueObject::DumpValueObject (*output_stream,
842 valobj_sp.get(),
Enrico Granata0c489f52012-03-01 04:24:26 +0000843 options);
Greg Clayton84c39662011-04-27 22:04:39 +0000844 }
845 else
846 {
847 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
848 view_as_type_cstr,
849 name_strm.GetString().c_str());
850 result.SetStatus(eReturnStatusFailed);
851 return false;
852 }
853 }
854 return true;
855 }
856
857 result.SetStatus(eReturnStatusSuccessFinishResult);
858 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000859 target->GetArchitecture().GetByteOrder(),
860 target->GetArchitecture().GetAddressByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000861
862 Format format = m_format_options.GetFormat();
863 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
864 && (item_byte_size != 1)
865 && (item_count == 1))
866 {
867 // this turns requests such as
868 // memory read -fc -s10 -c1 *charPtrPtr
869 // which make no sense (what is a char of size 10?)
870 // into a request for fetching 10 chars of size 1 from the same memory location
871 format = eFormatCharArray;
872 item_count = item_byte_size;
873 item_byte_size = 1;
874 }
Greg Clayton84c39662011-04-27 22:04:39 +0000875
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000876 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000877 size_t bytes_dumped = data.Dump (output_stream,
878 0,
Enrico Granata31898912013-05-21 17:39:04 +0000879 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000880 item_byte_size,
881 item_count,
882 num_per_line,
883 addr,
884 0,
885 0,
886 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000887 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000888 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000889 return true;
890 }
891
Greg Clayton84c39662011-04-27 22:04:39 +0000892 OptionGroupOptions m_option_group;
893 OptionGroupFormat m_format_options;
894 OptionGroupReadMemory m_memory_options;
895 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000896 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000897 lldb::addr_t m_next_addr;
898 lldb::addr_t m_prev_byte_size;
899 OptionGroupFormat m_prev_format_options;
900 OptionGroupReadMemory m_prev_memory_options;
901 OptionGroupOutputFile m_prev_outfile_options;
902 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000903 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000904};
905
Greg Clayton1deb7962011-10-25 06:44:01 +0000906
907OptionDefinition
908g_memory_write_option_table[] =
909{
910{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
911{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
912};
913
914
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000915//----------------------------------------------------------------------
916// Write memory to the inferior process
917//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000918class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000919{
920public:
921
Greg Clayton1deb7962011-10-25 06:44:01 +0000922 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000923 {
924 public:
Greg Clayton1deb7962011-10-25 06:44:01 +0000925 OptionGroupWriteMemory () :
926 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000927 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000928 }
929
930 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +0000931 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000932 {
933 }
934
Greg Clayton1deb7962011-10-25 06:44:01 +0000935 virtual uint32_t
936 GetNumDefinitions ()
937 {
938 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
939 }
940
941 virtual const OptionDefinition*
942 GetDefinitions ()
943 {
944 return g_memory_write_option_table;
945 }
946
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000947 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000948 SetOptionValue (CommandInterpreter &interpreter,
949 uint32_t option_idx,
950 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000951 {
952 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000953 const int short_option = g_memory_write_option_table[option_idx].short_option;
Greg Clayton1deb7962011-10-25 06:44:01 +0000954
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000955 switch (short_option)
956 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000957 case 'i':
958 m_infile.SetFile (option_arg, true);
959 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000960 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000961 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +0000962 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000963 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000964 break;
965
966 case 'o':
967 {
968 bool success;
969 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
970 if (!success)
971 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000972 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +0000973 }
974 }
975 break;
976
977 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000978 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +0000979 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000980 }
981 return error;
982 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000983
984 virtual void
985 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000986 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000987 m_infile.Clear();
988 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000989 }
990
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000991 FileSpec m_infile;
992 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000993 };
994
Greg Claytona7015092010-09-18 01:14:36 +0000995 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000996 CommandObjectParsed (interpreter,
997 "memory write",
998 "Write to the memory of the process being debugged.",
999 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +00001000 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001001 m_option_group (interpreter),
1002 m_format_options (eFormatBytes, 1, UINT64_MAX),
1003 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001004 {
Caroline Tice405fe672010-10-04 22:28:36 +00001005 CommandArgumentEntry arg1;
1006 CommandArgumentEntry arg2;
1007 CommandArgumentData addr_arg;
1008 CommandArgumentData value_arg;
1009
1010 // Define the first (and only) variant of this arg.
1011 addr_arg.arg_type = eArgTypeAddress;
1012 addr_arg.arg_repetition = eArgRepeatPlain;
1013
1014 // There is only one variant this argument could be; put it into the argument entry.
1015 arg1.push_back (addr_arg);
1016
1017 // Define the first (and only) variant of this arg.
1018 value_arg.arg_type = eArgTypeValue;
1019 value_arg.arg_repetition = eArgRepeatPlus;
1020
1021 // There is only one variant this argument could be; put it into the argument entry.
1022 arg2.push_back (value_arg);
1023
1024 // Push the data for the first argument into the m_arguments vector.
1025 m_arguments.push_back (arg1);
1026 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001027
1028 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1029 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1030 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1031 m_option_group.Finalize();
1032
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001033 }
1034
1035 virtual
1036 ~CommandObjectMemoryWrite ()
1037 {
1038 }
1039
1040 Options *
1041 GetOptions ()
1042 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001043 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001044 }
1045
1046 bool
1047 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1048 {
1049 if (total_byte_size > 8)
1050 return false;
1051
1052 if (total_byte_size == 8)
1053 return true;
1054
1055 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1056 return uval64 <= max;
1057 }
1058
1059 bool
1060 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1061 {
1062 if (total_byte_size > 8)
1063 return false;
1064
1065 if (total_byte_size == 8)
1066 return true;
1067
1068 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1069 const int64_t min = ~(max);
1070 return min <= sval64 && sval64 <= max;
1071 }
1072
Jim Ingham5a988412012-06-08 21:56:10 +00001073protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001074 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001075 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001076 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001077 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1078 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001079
1080 const size_t argc = command.GetArgumentCount();
1081
Greg Clayton1deb7962011-10-25 06:44:01 +00001082 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001083 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001084 if (argc < 1)
1085 {
1086 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1087 result.SetStatus(eReturnStatusFailed);
1088 return false;
1089 }
1090 }
1091 else if (argc < 2)
1092 {
1093 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 +00001094 result.SetStatus(eReturnStatusFailed);
1095 return false;
1096 }
1097
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001098 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001099 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1100 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001101
Greg Clayton1deb7962011-10-25 06:44:01 +00001102 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1103 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001104
Greg Claytonb9d5df52012-12-06 22:49:16 +00001105 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001106 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001107 command.GetArgumentAtIndex(0),
1108 LLDB_INVALID_ADDRESS,
1109 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001110
1111 if (addr == LLDB_INVALID_ADDRESS)
1112 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001113 result.AppendError("invalid address expression\n");
1114 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001115 result.SetStatus(eReturnStatusFailed);
1116 return false;
1117 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001118
Greg Clayton1deb7962011-10-25 06:44:01 +00001119 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001120 {
1121 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +00001122 if (item_byte_size > 0)
1123 length = item_byte_size;
1124 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001125 if (data_sp)
1126 {
1127 length = data_sp->GetByteSize();
1128 if (length > 0)
1129 {
1130 Error error;
1131 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1132
1133 if (bytes_written == length)
1134 {
1135 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001136 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001137 result.SetStatus(eReturnStatusSuccessFinishResult);
1138 }
1139 else if (bytes_written > 0)
1140 {
1141 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001142 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 +00001143 result.SetStatus(eReturnStatusSuccessFinishResult);
1144 }
1145 else
1146 {
Daniel Malead01b2952012-11-29 21:49:15 +00001147 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001148 result.SetStatus(eReturnStatusFailed);
1149 }
1150 }
1151 }
1152 else
1153 {
1154 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1155 result.SetStatus(eReturnStatusFailed);
1156 }
1157 return result.Succeeded();
1158 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001159 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001160 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001161 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001162 item_byte_size = buffer.GetAddressByteSize();
1163 else
1164 item_byte_size = 1;
1165 }
1166
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001167 command.Shift(); // shift off the address argument
1168 uint64_t uval64;
1169 int64_t sval64;
1170 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001171 const size_t num_value_args = command.GetArgumentCount();
1172 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001173 {
1174 const char *value_str = command.GetArgumentAtIndex(i);
1175
Greg Clayton1deb7962011-10-25 06:44:01 +00001176 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001177 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001178 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001179 case eFormatFloat: // TODO: add support for floats soon
1180 case eFormatCharPrintable:
1181 case eFormatBytesWithASCII:
1182 case eFormatComplex:
1183 case eFormatEnum:
1184 case eFormatUnicode16:
1185 case eFormatUnicode32:
1186 case eFormatVectorOfChar:
1187 case eFormatVectorOfSInt8:
1188 case eFormatVectorOfUInt8:
1189 case eFormatVectorOfSInt16:
1190 case eFormatVectorOfUInt16:
1191 case eFormatVectorOfSInt32:
1192 case eFormatVectorOfUInt32:
1193 case eFormatVectorOfSInt64:
1194 case eFormatVectorOfUInt64:
1195 case eFormatVectorOfFloat32:
1196 case eFormatVectorOfFloat64:
1197 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001198 case eFormatOSType:
1199 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001200 case eFormatAddressInfo:
1201 case eFormatHexFloat:
1202 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001203 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001204 result.AppendError("unsupported format for writing memory");
1205 result.SetStatus(eReturnStatusFailed);
1206 return false;
1207
1208 case eFormatDefault:
1209 case eFormatBytes:
1210 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001211 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001212 case eFormatPointer:
1213
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001214 // Decode hex bytes
1215 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1216 if (!success)
1217 {
1218 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1219 result.SetStatus(eReturnStatusFailed);
1220 return false;
1221 }
1222 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1223 {
Daniel Malead01b2952012-11-29 21:49:15 +00001224 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 +00001225 result.SetStatus(eReturnStatusFailed);
1226 return false;
1227 }
1228 buffer.PutMaxHex64 (uval64, item_byte_size);
1229 break;
1230
1231 case eFormatBoolean:
1232 uval64 = Args::StringToBoolean(value_str, false, &success);
1233 if (!success)
1234 {
1235 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1236 result.SetStatus(eReturnStatusFailed);
1237 return false;
1238 }
1239 buffer.PutMaxHex64 (uval64, item_byte_size);
1240 break;
1241
1242 case eFormatBinary:
1243 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1244 if (!success)
1245 {
1246 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1247 result.SetStatus(eReturnStatusFailed);
1248 return false;
1249 }
1250 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1251 {
Daniel Malead01b2952012-11-29 21:49:15 +00001252 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 +00001253 result.SetStatus(eReturnStatusFailed);
1254 return false;
1255 }
1256 buffer.PutMaxHex64 (uval64, item_byte_size);
1257 break;
1258
Greg Clayton4e4294b2011-06-17 23:50:44 +00001259 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001260 case eFormatChar:
1261 case eFormatCString:
1262 if (value_str[0])
1263 {
1264 size_t len = strlen (value_str);
1265 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001266 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001267 ++len;
1268 Error error;
1269 if (process->WriteMemory (addr, value_str, len, error) == len)
1270 {
1271 addr += len;
1272 }
1273 else
1274 {
Daniel Malead01b2952012-11-29 21:49:15 +00001275 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001276 result.SetStatus(eReturnStatusFailed);
1277 return false;
1278 }
1279 }
1280 break;
1281
1282 case eFormatDecimal:
1283 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1284 if (!success)
1285 {
1286 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1287 result.SetStatus(eReturnStatusFailed);
1288 return false;
1289 }
1290 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1291 {
Daniel Malead01b2952012-11-29 21:49:15 +00001292 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 +00001293 result.SetStatus(eReturnStatusFailed);
1294 return false;
1295 }
1296 buffer.PutMaxHex64 (sval64, item_byte_size);
1297 break;
1298
1299 case eFormatUnsigned:
1300 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1301 if (!success)
1302 {
1303 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1304 result.SetStatus(eReturnStatusFailed);
1305 return false;
1306 }
1307 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1308 {
Daniel Malead01b2952012-11-29 21:49:15 +00001309 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 +00001310 result.SetStatus(eReturnStatusFailed);
1311 return false;
1312 }
1313 buffer.PutMaxHex64 (uval64, item_byte_size);
1314 break;
1315
1316 case eFormatOctal:
1317 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1318 if (!success)
1319 {
1320 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1321 result.SetStatus(eReturnStatusFailed);
1322 return false;
1323 }
1324 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1325 {
Daniel Malead01b2952012-11-29 21:49:15 +00001326 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 +00001327 result.SetStatus(eReturnStatusFailed);
1328 return false;
1329 }
1330 buffer.PutMaxHex64 (uval64, item_byte_size);
1331 break;
1332 }
1333 }
1334
1335 if (!buffer.GetString().empty())
1336 {
1337 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001338 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001339 return true;
1340 else
1341 {
Daniel Malead01b2952012-11-29 21:49:15 +00001342 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001343 result.SetStatus(eReturnStatusFailed);
1344 return false;
1345 }
1346 }
1347 return true;
1348 }
1349
Greg Clayton1deb7962011-10-25 06:44:01 +00001350 OptionGroupOptions m_option_group;
1351 OptionGroupFormat m_format_options;
1352 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001353};
1354
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001355
1356//-------------------------------------------------------------------------
1357// CommandObjectMemory
1358//-------------------------------------------------------------------------
1359
Greg Clayton66111032010-06-23 01:19:29 +00001360CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001361 CommandObjectMultiword (interpreter,
1362 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001363 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001364 "memory <subcommand> [<subcommand-options>]")
1365{
Greg Claytona7015092010-09-18 01:14:36 +00001366 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1367 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001368}
1369
1370CommandObjectMemory::~CommandObjectMemory ()
1371{
1372}