blob: d7e59fb348694899ecbdefb23e8b7a637376536d [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"
Enrico Granata4d93b8c2013-09-30 19:11:51 +000026#include "lldb/DataFormatters/ValueObjectPrinter.h"
Greg Clayton66111032010-06-23 01:19:29 +000027#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000029#include "lldb/Interpreter/CommandInterpreter.h"
30#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000031#include "lldb/Interpreter/OptionGroupFormat.h"
32#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000033#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000034#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton1f746072012-08-29 21:13:06 +000035#include "lldb/Symbol/TypeList.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036#include "lldb/Target/Process.h"
Greg Clayton84c39662011-04-27 22:04:39 +000037#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038
39using namespace lldb;
40using namespace lldb_private;
41
Greg Clayton68ebae62011-04-28 20:55:26 +000042static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000043g_option_table[] =
44{
Virgile Belloe2607b52013-09-05 16:42:23 +000045 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
46 { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , 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."},
47 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton2346fcf2012-11-02 21:14:58 +000048 { LLDB_OPT_SET_1|
49 LLDB_OPT_SET_2|
Virgile Belloe2607b52013-09-05 16:42:23 +000050 LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
Greg Clayton84c39662011-04-27 22:04:39 +000051};
52
53
54
55class OptionGroupReadMemory : public OptionGroup
56{
57public:
58
59 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000060 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000061 m_output_as_binary (false),
62 m_view_as_type()
63 {
64 }
65
66 virtual
67 ~OptionGroupReadMemory ()
68 {
69 }
70
71
72 virtual uint32_t
73 GetNumDefinitions ()
74 {
75 return sizeof (g_option_table) / sizeof (OptionDefinition);
76 }
77
78 virtual const OptionDefinition*
79 GetDefinitions ()
80 {
81 return g_option_table;
82 }
83
84 virtual Error
85 SetOptionValue (CommandInterpreter &interpreter,
86 uint32_t option_idx,
87 const char *option_arg)
88 {
89 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000090 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000091
92 switch (short_option)
93 {
94 case 'l':
95 error = m_num_per_line.SetValueFromCString (option_arg);
96 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +000097 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +000098 break;
Greg Clayton1deb7962011-10-25 06:44:01 +000099
Greg Clayton84c39662011-04-27 22:04:39 +0000100 case 'b':
101 m_output_as_binary = true;
102 break;
103
104 case 't':
105 error = m_view_as_type.SetValueFromCString (option_arg);
106 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000107
108 case 'r':
109 m_force = true;
110 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000111
112 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000113 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000114 break;
115 }
116 return error;
117 }
118
119 virtual void
120 OptionParsingStarting (CommandInterpreter &interpreter)
121 {
Greg Clayton84c39662011-04-27 22:04:39 +0000122 m_num_per_line.Clear();
123 m_output_as_binary = false;
124 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000125 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000126 }
127
Greg Clayton68ebae62011-04-28 20:55:26 +0000128 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000129 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000130 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000131 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000132 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
133 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000134 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000135 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000136 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000137
Greg Clayton68ebae62011-04-28 20:55:26 +0000138 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000139 {
140 default:
141 break;
142
143 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000144 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000145 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000146 if (!num_per_line_option_set)
147 m_num_per_line = 1;
148 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000149 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000150 break;
151
152 case eFormatCString:
153 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000154
155 case eFormatInstruction:
156 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000157 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000158 m_num_per_line = 1;
159 break;
160
161 case eFormatAddressInfo:
162 if (!byte_size_option_set)
163 byte_size_value = target->GetArchitecture().GetAddressByteSize();
164 m_num_per_line = 1;
165 if (!count_option_set)
166 format_options.GetCountValue() = 8;
167 break;
168
Greg Clayton84c39662011-04-27 22:04:39 +0000169 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000170 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000171 if (!num_per_line_option_set)
172 m_num_per_line = 4;
173 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000174 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000175 break;
176
177 case eFormatBinary:
178 case eFormatFloat:
179 case eFormatOctal:
180 case eFormatDecimal:
181 case eFormatEnum:
182 case eFormatUnicode16:
183 case eFormatUnicode32:
184 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000185 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000186 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000187 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000188 if (!num_per_line_option_set)
189 m_num_per_line = 1;
190 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000191 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000192 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000193
Greg Clayton84c39662011-04-27 22:04:39 +0000194 case eFormatBytes:
195 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000196 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000197 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000198 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000199 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000200 "\tconsider using a different display format or don't specify the byte size",
201 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000202 }
203 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000204 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000205 if (!num_per_line_option_set)
206 m_num_per_line = 16;
207 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000208 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000209 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000210 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000211 case eFormatChar:
212 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000213 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000214 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000215 if (!num_per_line_option_set)
216 m_num_per_line = 32;
217 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000218 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000219 break;
220 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000221 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000222 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000223 if (!num_per_line_option_set)
224 m_num_per_line = 1;
225 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000226 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000227 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000228 case eFormatComplexInteger:
229 if (!byte_size_option_set)
230 byte_size_value = 8;
231 if (!num_per_line_option_set)
232 m_num_per_line = 1;
233 if (!count_option_set)
234 format_options.GetCountValue() = 8;
235 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000236 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000237 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000238 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000239 if (!num_per_line_option_set)
240 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000241 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000242 {
243 case 1:
244 case 2:
245 m_num_per_line = 8;
246 break;
247 case 4:
248 m_num_per_line = 4;
249 break;
250 case 8:
251 m_num_per_line = 2;
252 break;
253 default:
254 m_num_per_line = 1;
255 break;
256 }
257 }
258 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000259 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000260 break;
261
262 case eFormatVectorOfChar:
263 case eFormatVectorOfSInt8:
264 case eFormatVectorOfUInt8:
265 case eFormatVectorOfSInt16:
266 case eFormatVectorOfUInt16:
267 case eFormatVectorOfSInt32:
268 case eFormatVectorOfUInt32:
269 case eFormatVectorOfSInt64:
270 case eFormatVectorOfUInt64:
271 case eFormatVectorOfFloat32:
272 case eFormatVectorOfFloat64:
273 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000274 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000275 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000276 if (!num_per_line_option_set)
277 m_num_per_line = 1;
278 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000279 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000280 break;
281 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000282 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000283 }
284
Greg Clayton82f4cf42011-10-26 04:32:38 +0000285 bool
286 AnyOptionWasSet () const
287 {
288 return m_num_per_line.OptionWasSet() ||
289 m_output_as_binary ||
290 m_view_as_type.OptionWasSet();
291 }
292
Greg Clayton84c39662011-04-27 22:04:39 +0000293 OptionValueUInt64 m_num_per_line;
294 bool m_output_as_binary;
295 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000296 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000297};
298
299
300
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000301//----------------------------------------------------------------------
302// Read memory from the inferior process
303//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000304class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305{
306public:
307
Greg Claytona7015092010-09-18 01:14:36 +0000308 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000309 CommandObjectParsed (interpreter,
310 "memory read",
311 "Read from the memory of the process being debugged.",
312 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000313 eFlagRequiresTarget | eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000314 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000315 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000316 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000317 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000318 m_varobj_options(),
319 m_next_addr(LLDB_INVALID_ADDRESS),
320 m_prev_byte_size(0),
321 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
322 m_prev_memory_options (),
323 m_prev_outfile_options (),
324 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325 {
Caroline Tice405fe672010-10-04 22:28:36 +0000326 CommandArgumentEntry arg1;
327 CommandArgumentEntry arg2;
328 CommandArgumentData start_addr_arg;
329 CommandArgumentData end_addr_arg;
330
331 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000332 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000333 start_addr_arg.arg_repetition = eArgRepeatPlain;
334
335 // There is only one variant this argument could be; put it into the argument entry.
336 arg1.push_back (start_addr_arg);
337
338 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000339 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000340 end_addr_arg.arg_repetition = eArgRepeatOptional;
341
342 // There is only one variant this argument could be; put it into the argument entry.
343 arg2.push_back (end_addr_arg);
344
345 // Push the data for the first argument into the m_arguments vector.
346 m_arguments.push_back (arg1);
347 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000348
Greg Clayton1deb7962011-10-25 06:44:01 +0000349 // Add the "--format" and "--count" options to group 1 and 3
350 m_option_group.Append (&m_format_options,
351 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000352 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000353 m_option_group.Append (&m_format_options,
354 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000355 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000356 // Add the "--size" option to group 1 and 2
357 m_option_group.Append (&m_format_options,
358 OptionGroupFormat::OPTION_GROUP_SIZE,
359 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000360 m_option_group.Append (&m_memory_options);
361 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 +0000362 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000363 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364 }
365
366 virtual
367 ~CommandObjectMemoryRead ()
368 {
369 }
370
371 Options *
372 GetOptions ()
373 {
Greg Clayton84c39662011-04-27 22:04:39 +0000374 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000375 }
376
Greg Clayton82f4cf42011-10-26 04:32:38 +0000377 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
378 {
379 return m_cmd_name.c_str();
380 }
381
Jim Ingham5a988412012-06-08 21:56:10 +0000382protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000383 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000384 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000386 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
387 Target *target = m_exe_ctx.GetTargetPtr();
388
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000389 const size_t argc = command.GetArgumentCount();
390
Greg Clayton82f4cf42011-10-26 04:32:38 +0000391 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000393 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 +0000394 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000395 result.SetStatus(eReturnStatusFailed);
396 return false;
397 }
398
Greg Clayton68ebae62011-04-28 20:55:26 +0000399 ClangASTType clang_ast_type;
400 Error error;
401
Greg Clayton84c39662011-04-27 22:04:39 +0000402 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
403 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000404 {
Greg Clayton84c39662011-04-27 22:04:39 +0000405 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000406
Greg Clayton84c39662011-04-27 22:04:39 +0000407 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000408 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000409 TypeList type_list;
410 uint32_t reference_count = 0;
411 uint32_t pointer_count = 0;
412 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000413
414#define ALL_KEYWORDS \
415 KEYWORD("const") \
416 KEYWORD("volatile") \
417 KEYWORD("restrict") \
418 KEYWORD("struct") \
419 KEYWORD("class") \
420 KEYWORD("union")
421
422#define KEYWORD(s) s,
423 static const char *g_keywords[] =
424 {
425 ALL_KEYWORDS
426 };
427#undef KEYWORD
428
429#define KEYWORD(s) (sizeof(s) - 1),
430 static const int g_keyword_lengths[] =
431 {
432 ALL_KEYWORDS
433 };
434#undef KEYWORD
435
436#undef ALL_KEYWORDS
437
438 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000439 std::string type_str(view_as_type_cstr);
440
441 // Remove all instances of g_keywords that are followed by spaces
442 for (size_t i = 0; i < g_num_keywords; ++i)
443 {
444 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000445 int keyword_len = g_keyword_lengths[i];
446
447 idx = 0;
448 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000449 {
450 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000451 {
Greg Clayton84c39662011-04-27 22:04:39 +0000452 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000453 idx = 0;
454 }
455 else
456 {
457 idx += keyword_len;
458 }
Greg Clayton84c39662011-04-27 22:04:39 +0000459 }
460 }
461 bool done = type_str.empty();
462 //
463 idx = type_str.find_first_not_of (" \t");
464 if (idx > 0 && idx != std::string::npos)
465 type_str.erase (0, idx);
466 while (!done)
467 {
468 // Strip trailing spaces
469 if (type_str.empty())
470 done = true;
471 else
472 {
473 switch (type_str[type_str.size()-1])
474 {
475 case '*':
476 ++pointer_count;
477 // fall through...
478 case ' ':
479 case '\t':
480 type_str.erase(type_str.size()-1);
481 break;
482
483 case '&':
484 if (reference_count == 0)
485 {
486 reference_count = 1;
487 type_str.erase(type_str.size()-1);
488 }
489 else
490 {
491 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
492 result.SetStatus(eReturnStatusFailed);
493 return false;
494 }
495 break;
496
497 default:
498 done = true;
499 break;
500 }
501 }
502 }
503
504 ConstString lookup_type_name(type_str.c_str());
Greg Claytonf9fc6092013-01-09 19:44:40 +0000505 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000506 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000507 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000508 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000509 if (sc.module_sp)
510 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000511 sc.module_sp->FindTypes (sc,
512 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000513 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000514 1,
515 type_list);
516 }
517 }
518 if (type_list.GetSize() == 0)
519 {
Greg Clayton29399a22012-04-06 17:41:13 +0000520 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000521 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000522 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000523 1,
524 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000525 }
526
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000527 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000528 {
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000529 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
530 if (tdecl)
531 {
532 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
533 }
Greg Clayton84c39662011-04-27 22:04:39 +0000534 }
535
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000536 if (clang_ast_type.IsValid() == false)
537 {
538 if (type_list.GetSize() == 0)
539 {
540 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
541 lookup_type_name.GetCString(),
542 view_as_type_cstr);
543 result.SetStatus(eReturnStatusFailed);
544 return false;
545 }
546 else
547 {
548 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton57ee3062013-07-11 22:46:58 +0000549 clang_ast_type = type_sp->GetClangFullType();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000550 }
551 }
Greg Clayton84c39662011-04-27 22:04:39 +0000552
553 while (pointer_count > 0)
554 {
Greg Clayton57ee3062013-07-11 22:46:58 +0000555 ClangASTType pointer_type = clang_ast_type.GetPointerType();
556 if (pointer_type.IsValid())
557 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000558 else
559 {
560 result.AppendError ("unable make a pointer type\n");
561 result.SetStatus(eReturnStatusFailed);
562 return false;
563 }
564 --pointer_count;
565 }
566
Greg Clayton57ee3062013-07-11 22:46:58 +0000567 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize();
Greg Clayton84c39662011-04-27 22:04:39 +0000568
Greg Clayton1deb7962011-10-25 06:44:01 +0000569 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000570 {
571 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
572 view_as_type_cstr);
573 result.SetStatus(eReturnStatusFailed);
574 return false;
575 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000576
Greg Clayton1deb7962011-10-25 06:44:01 +0000577 if (!m_format_options.GetCountValue().OptionWasSet())
578 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000579 }
580 else
581 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000582 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000583 }
584
585 // Look for invalid combinations of settings
586 if (error.Fail())
587 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000588 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000589 result.SetStatus(eReturnStatusFailed);
590 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000591 }
592
Greg Clayton82f4cf42011-10-26 04:32:38 +0000593 lldb::addr_t addr;
594 size_t total_byte_size = 0;
595 if (argc == 0)
596 {
597 // Use the last address and byte size and all options as they were
598 // if no options have been set
599 addr = m_next_addr;
600 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000601 clang_ast_type = m_prev_clang_ast_type;
602 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000603 !m_memory_options.AnyOptionWasSet() &&
604 !m_outfile_options.AnyOptionWasSet() &&
605 !m_varobj_options.AnyOptionWasSet())
606 {
607 m_format_options = m_prev_format_options;
608 m_memory_options = m_prev_memory_options;
609 m_outfile_options = m_prev_outfile_options;
610 m_varobj_options = m_prev_varobj_options;
611 }
612 }
613
Greg Clayton1deb7962011-10-25 06:44:01 +0000614 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000615 size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000616 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000617
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000618 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000619 {
620 total_byte_size = item_count * item_byte_size;
621 if (total_byte_size == 0)
622 total_byte_size = 32;
623 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000624
Greg Clayton82f4cf42011-10-26 04:32:38 +0000625 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000626 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000627
628 if (addr == LLDB_INVALID_ADDRESS)
629 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000630 result.AppendError("invalid start address expression.");
631 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000632 result.SetStatus(eReturnStatusFailed);
633 return false;
634 }
635
636 if (argc == 2)
637 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000638 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000639 if (end_addr == LLDB_INVALID_ADDRESS)
640 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000641 result.AppendError("invalid end address expression.");
642 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000643 result.SetStatus(eReturnStatusFailed);
644 return false;
645 }
646 else if (end_addr <= addr)
647 {
Daniel Malead01b2952012-11-29 21:49:15 +0000648 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 +0000649 result.SetStatus(eReturnStatusFailed);
650 return false;
651 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000652 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000653 {
Daniel Malead01b2952012-11-29 21:49:15 +0000654 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 +0000655 result.SetStatus(eReturnStatusFailed);
656 return false;
657 }
658
659 total_byte_size = end_addr - addr;
660 item_count = total_byte_size / item_byte_size;
661 }
Greg Clayton84c39662011-04-27 22:04:39 +0000662
Enrico Granatad325bf92013-06-04 22:54:16 +0000663 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
664
665 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000666 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000667 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
668 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
669 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 +0000670 return false;
671 }
672
Greg Clayton84c39662011-04-27 22:04:39 +0000673 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000674 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000675 if (clang_ast_type.GetOpaqueQualType())
676 {
677 // Make sure we don't display our type as ASCII bytes like the default memory read
678 if (m_format_options.GetFormatValue().OptionWasSet() == false)
679 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
680
Greg Clayton57ee3062013-07-11 22:46:58 +0000681 bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000682 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000683 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000684 {
Greg Clayton84c39662011-04-27 22:04:39 +0000685 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000686 if (data_sp->GetBytes() == NULL)
687 {
688 result.AppendErrorWithFormat ("can't allocate 0x%zx bytes for the memory read buffer, specify a smaller size to read", total_byte_size);
689 result.SetStatus(eReturnStatusFailed);
690 return false;
691 }
692
Greg Claytone72dfb32012-02-24 01:59:29 +0000693 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000694 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000695 if (bytes_read == 0)
696 {
Greg Clayton57f06302012-05-25 17:05:55 +0000697 const char *error_cstr = error.AsCString();
698 if (error_cstr && error_cstr[0])
699 {
700 result.AppendError(error_cstr);
701 }
702 else
703 {
Daniel Malead01b2952012-11-29 21:49:15 +0000704 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000705 }
Greg Clayton84c39662011-04-27 22:04:39 +0000706 result.SetStatus(eReturnStatusFailed);
707 return false;
708 }
709
710 if (bytes_read < total_byte_size)
Jim Ingham9d8dd4b2013-01-25 23:05:01 +0000711 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 +0000712 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000713 else
714 {
715 // we treat c-strings as a special case because they do not have a fixed size
716 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
717 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
718 else
719 item_byte_size = target->GetMaximumSizeOfStringSummary();
720 if (!m_format_options.GetCountValue().OptionWasSet())
721 item_count = 1;
722 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000723 if (data_sp->GetBytes() == NULL)
724 {
725 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));
726 result.SetStatus(eReturnStatusFailed);
727 return false;
728 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000729 uint8_t *data_ptr = data_sp->GetBytes();
730 auto data_addr = addr;
731 auto count = item_count;
732 item_count = 0;
733 while (item_count < count)
734 {
735 std::string buffer;
736 buffer.resize(item_byte_size+1,0);
737 Error error;
738 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
739 if (error.Fail())
740 {
741 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
742 result.SetStatus(eReturnStatusFailed);
743 return false;
744 }
745 if (item_byte_size == read)
746 {
747 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
748 break;
749 }
750 read+=1; // account for final NULL byte
751 memcpy(data_ptr, &buffer[0], read);
752 data_ptr += read;
753 data_addr += read;
754 bytes_read += read;
755 item_count++; // if we break early we know we only read item_count strings
756 }
757 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
758 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000759
Greg Clayton2e1f7452012-12-15 02:08:17 +0000760 m_next_addr = addr + bytes_read;
761 m_prev_byte_size = bytes_read;
762 m_prev_format_options = m_format_options;
763 m_prev_memory_options = m_memory_options;
764 m_prev_outfile_options = m_outfile_options;
765 m_prev_varobj_options = m_varobj_options;
766 m_prev_clang_ast_type = clang_ast_type;
767
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000768 StreamFile outfile_stream;
769 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000770 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
771 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000772 {
773 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000774 outfile_spec.GetPath (path, sizeof(path));
775
776 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
777 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
778 if (append)
779 open_options |= File::eOpenOptionAppend;
780
781 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000782 {
Greg Clayton84c39662011-04-27 22:04:39 +0000783 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000784 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000785 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000786 if (bytes_written > 0)
787 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000788 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000789 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000790 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000791 path);
792 return true;
793 }
794 else
795 {
Daniel Malead01b2952012-11-29 21:49:15 +0000796 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000797 result.SetStatus(eReturnStatusFailed);
798 return false;
799 }
800 }
801 else
802 {
803 // We are going to write ASCII to the file just point the
804 // output_stream to our outfile_stream...
805 output_stream = &outfile_stream;
806 }
807 }
808 else
809 {
Greg Clayton84c39662011-04-27 22:04:39 +0000810 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000811 result.SetStatus(eReturnStatusFailed);
812 return false;
813 }
814 }
815 else
816 {
817 output_stream = &result.GetOutputStream();
818 }
819
Greg Clayton84c39662011-04-27 22:04:39 +0000820
Greg Claytonf9fc6092013-01-09 19:44:40 +0000821 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000822 if (clang_ast_type.GetOpaqueQualType())
823 {
824 for (uint32_t i = 0; i<item_count; ++i)
825 {
826 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000827 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000828 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000829 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000830 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000831 name_strm.GetString().c_str(),
832 address,
833 clang_ast_type));
834 if (valobj_sp)
835 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000836 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000837 if (format != eFormatDefault)
838 valobj_sp->SetFormat (format);
839
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000840 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000841
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000842 valobj_sp->Dump(*output_stream,options);
Greg Clayton84c39662011-04-27 22:04:39 +0000843 }
844 else
845 {
846 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
847 view_as_type_cstr,
848 name_strm.GetString().c_str());
849 result.SetStatus(eReturnStatusFailed);
850 return false;
851 }
852 }
853 return true;
854 }
855
856 result.SetStatus(eReturnStatusSuccessFinishResult);
857 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000858 target->GetArchitecture().GetByteOrder(),
859 target->GetArchitecture().GetAddressByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000860
861 Format format = m_format_options.GetFormat();
862 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
863 && (item_byte_size != 1)
864 && (item_count == 1))
865 {
866 // this turns requests such as
867 // memory read -fc -s10 -c1 *charPtrPtr
868 // which make no sense (what is a char of size 10?)
869 // into a request for fetching 10 chars of size 1 from the same memory location
870 format = eFormatCharArray;
871 item_count = item_byte_size;
872 item_byte_size = 1;
873 }
Greg Clayton84c39662011-04-27 22:04:39 +0000874
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000875 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000876 size_t bytes_dumped = data.Dump (output_stream,
877 0,
Enrico Granata31898912013-05-21 17:39:04 +0000878 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000879 item_byte_size,
880 item_count,
881 num_per_line,
882 addr,
883 0,
884 0,
885 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000886 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000887 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000888 return true;
889 }
890
Greg Clayton84c39662011-04-27 22:04:39 +0000891 OptionGroupOptions m_option_group;
892 OptionGroupFormat m_format_options;
893 OptionGroupReadMemory m_memory_options;
894 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000895 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000896 lldb::addr_t m_next_addr;
897 lldb::addr_t m_prev_byte_size;
898 OptionGroupFormat m_prev_format_options;
899 OptionGroupReadMemory m_prev_memory_options;
900 OptionGroupOutputFile m_prev_outfile_options;
901 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000902 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000903};
904
Greg Clayton1deb7962011-10-25 06:44:01 +0000905
906OptionDefinition
907g_memory_write_option_table[] =
908{
Virgile Belloe2607b52013-09-05 16:42:23 +0000909{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
910{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
Greg Clayton1deb7962011-10-25 06:44:01 +0000911};
912
913
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000914//----------------------------------------------------------------------
915// Write memory to the inferior process
916//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000917class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000918{
919public:
920
Greg Clayton1deb7962011-10-25 06:44:01 +0000921 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000922 {
923 public:
Greg Clayton1deb7962011-10-25 06:44:01 +0000924 OptionGroupWriteMemory () :
925 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000926 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000927 }
928
929 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +0000930 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000931 {
932 }
933
Greg Clayton1deb7962011-10-25 06:44:01 +0000934 virtual uint32_t
935 GetNumDefinitions ()
936 {
937 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
938 }
939
940 virtual const OptionDefinition*
941 GetDefinitions ()
942 {
943 return g_memory_write_option_table;
944 }
945
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000946 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000947 SetOptionValue (CommandInterpreter &interpreter,
948 uint32_t option_idx,
949 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000950 {
951 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000952 const int short_option = g_memory_write_option_table[option_idx].short_option;
Greg Clayton1deb7962011-10-25 06:44:01 +0000953
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000954 switch (short_option)
955 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000956 case 'i':
957 m_infile.SetFile (option_arg, true);
958 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000959 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000960 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +0000961 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000962 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000963 break;
964
965 case 'o':
966 {
967 bool success;
968 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
969 if (!success)
970 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000971 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +0000972 }
973 }
974 break;
975
976 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000977 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +0000978 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000979 }
980 return error;
981 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000982
983 virtual void
984 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000985 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000986 m_infile.Clear();
987 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000988 }
989
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000990 FileSpec m_infile;
991 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000992 };
993
Greg Claytona7015092010-09-18 01:14:36 +0000994 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000995 CommandObjectParsed (interpreter,
996 "memory write",
997 "Write to the memory of the process being debugged.",
998 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000999 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001000 m_option_group (interpreter),
1001 m_format_options (eFormatBytes, 1, UINT64_MAX),
1002 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001003 {
Caroline Tice405fe672010-10-04 22:28:36 +00001004 CommandArgumentEntry arg1;
1005 CommandArgumentEntry arg2;
1006 CommandArgumentData addr_arg;
1007 CommandArgumentData value_arg;
1008
1009 // Define the first (and only) variant of this arg.
1010 addr_arg.arg_type = eArgTypeAddress;
1011 addr_arg.arg_repetition = eArgRepeatPlain;
1012
1013 // There is only one variant this argument could be; put it into the argument entry.
1014 arg1.push_back (addr_arg);
1015
1016 // Define the first (and only) variant of this arg.
1017 value_arg.arg_type = eArgTypeValue;
1018 value_arg.arg_repetition = eArgRepeatPlus;
1019
1020 // There is only one variant this argument could be; put it into the argument entry.
1021 arg2.push_back (value_arg);
1022
1023 // Push the data for the first argument into the m_arguments vector.
1024 m_arguments.push_back (arg1);
1025 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001026
1027 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1028 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1029 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1030 m_option_group.Finalize();
1031
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001032 }
1033
1034 virtual
1035 ~CommandObjectMemoryWrite ()
1036 {
1037 }
1038
1039 Options *
1040 GetOptions ()
1041 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001042 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001043 }
1044
1045 bool
1046 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1047 {
1048 if (total_byte_size > 8)
1049 return false;
1050
1051 if (total_byte_size == 8)
1052 return true;
1053
1054 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1055 return uval64 <= max;
1056 }
1057
1058 bool
1059 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1060 {
1061 if (total_byte_size > 8)
1062 return false;
1063
1064 if (total_byte_size == 8)
1065 return true;
1066
1067 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1068 const int64_t min = ~(max);
1069 return min <= sval64 && sval64 <= max;
1070 }
1071
Jim Ingham5a988412012-06-08 21:56:10 +00001072protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001073 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001074 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001075 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001076 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1077 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001078
1079 const size_t argc = command.GetArgumentCount();
1080
Greg Clayton1deb7962011-10-25 06:44:01 +00001081 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001082 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001083 if (argc < 1)
1084 {
1085 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1086 result.SetStatus(eReturnStatusFailed);
1087 return false;
1088 }
1089 }
1090 else if (argc < 2)
1091 {
1092 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 +00001093 result.SetStatus(eReturnStatusFailed);
1094 return false;
1095 }
1096
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001097 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001098 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1099 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001100
Greg Clayton1deb7962011-10-25 06:44:01 +00001101 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1102 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001103
Greg Claytonb9d5df52012-12-06 22:49:16 +00001104 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001105 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001106 command.GetArgumentAtIndex(0),
1107 LLDB_INVALID_ADDRESS,
1108 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001109
1110 if (addr == LLDB_INVALID_ADDRESS)
1111 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001112 result.AppendError("invalid address expression\n");
1113 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001114 result.SetStatus(eReturnStatusFailed);
1115 return false;
1116 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001117
Greg Clayton1deb7962011-10-25 06:44:01 +00001118 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001119 {
1120 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +00001121 if (item_byte_size > 0)
1122 length = item_byte_size;
1123 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001124 if (data_sp)
1125 {
1126 length = data_sp->GetByteSize();
1127 if (length > 0)
1128 {
1129 Error error;
1130 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1131
1132 if (bytes_written == length)
1133 {
1134 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001135 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001136 result.SetStatus(eReturnStatusSuccessFinishResult);
1137 }
1138 else if (bytes_written > 0)
1139 {
1140 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001141 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 +00001142 result.SetStatus(eReturnStatusSuccessFinishResult);
1143 }
1144 else
1145 {
Daniel Malead01b2952012-11-29 21:49:15 +00001146 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001147 result.SetStatus(eReturnStatusFailed);
1148 }
1149 }
1150 }
1151 else
1152 {
1153 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1154 result.SetStatus(eReturnStatusFailed);
1155 }
1156 return result.Succeeded();
1157 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001158 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001159 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001160 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001161 item_byte_size = buffer.GetAddressByteSize();
1162 else
1163 item_byte_size = 1;
1164 }
1165
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001166 command.Shift(); // shift off the address argument
1167 uint64_t uval64;
1168 int64_t sval64;
1169 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001170 const size_t num_value_args = command.GetArgumentCount();
1171 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001172 {
1173 const char *value_str = command.GetArgumentAtIndex(i);
1174
Greg Clayton1deb7962011-10-25 06:44:01 +00001175 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001176 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001177 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001178 case eFormatFloat: // TODO: add support for floats soon
1179 case eFormatCharPrintable:
1180 case eFormatBytesWithASCII:
1181 case eFormatComplex:
1182 case eFormatEnum:
1183 case eFormatUnicode16:
1184 case eFormatUnicode32:
1185 case eFormatVectorOfChar:
1186 case eFormatVectorOfSInt8:
1187 case eFormatVectorOfUInt8:
1188 case eFormatVectorOfSInt16:
1189 case eFormatVectorOfUInt16:
1190 case eFormatVectorOfSInt32:
1191 case eFormatVectorOfUInt32:
1192 case eFormatVectorOfSInt64:
1193 case eFormatVectorOfUInt64:
1194 case eFormatVectorOfFloat32:
1195 case eFormatVectorOfFloat64:
1196 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001197 case eFormatOSType:
1198 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001199 case eFormatAddressInfo:
1200 case eFormatHexFloat:
1201 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001202 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001203 result.AppendError("unsupported format for writing memory");
1204 result.SetStatus(eReturnStatusFailed);
1205 return false;
1206
1207 case eFormatDefault:
1208 case eFormatBytes:
1209 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001210 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001211 case eFormatPointer:
1212
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001213 // Decode hex bytes
1214 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1215 if (!success)
1216 {
1217 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1218 result.SetStatus(eReturnStatusFailed);
1219 return false;
1220 }
1221 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1222 {
Daniel Malead01b2952012-11-29 21:49:15 +00001223 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 +00001224 result.SetStatus(eReturnStatusFailed);
1225 return false;
1226 }
1227 buffer.PutMaxHex64 (uval64, item_byte_size);
1228 break;
1229
1230 case eFormatBoolean:
1231 uval64 = Args::StringToBoolean(value_str, false, &success);
1232 if (!success)
1233 {
1234 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1235 result.SetStatus(eReturnStatusFailed);
1236 return false;
1237 }
1238 buffer.PutMaxHex64 (uval64, item_byte_size);
1239 break;
1240
1241 case eFormatBinary:
1242 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1243 if (!success)
1244 {
1245 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1246 result.SetStatus(eReturnStatusFailed);
1247 return false;
1248 }
1249 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1250 {
Daniel Malead01b2952012-11-29 21:49:15 +00001251 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 +00001252 result.SetStatus(eReturnStatusFailed);
1253 return false;
1254 }
1255 buffer.PutMaxHex64 (uval64, item_byte_size);
1256 break;
1257
Greg Clayton4e4294b2011-06-17 23:50:44 +00001258 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001259 case eFormatChar:
1260 case eFormatCString:
1261 if (value_str[0])
1262 {
1263 size_t len = strlen (value_str);
1264 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001265 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001266 ++len;
1267 Error error;
1268 if (process->WriteMemory (addr, value_str, len, error) == len)
1269 {
1270 addr += len;
1271 }
1272 else
1273 {
Daniel Malead01b2952012-11-29 21:49:15 +00001274 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001275 result.SetStatus(eReturnStatusFailed);
1276 return false;
1277 }
1278 }
1279 break;
1280
1281 case eFormatDecimal:
1282 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1283 if (!success)
1284 {
1285 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1286 result.SetStatus(eReturnStatusFailed);
1287 return false;
1288 }
1289 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1290 {
Daniel Malead01b2952012-11-29 21:49:15 +00001291 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 +00001292 result.SetStatus(eReturnStatusFailed);
1293 return false;
1294 }
1295 buffer.PutMaxHex64 (sval64, item_byte_size);
1296 break;
1297
1298 case eFormatUnsigned:
1299 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1300 if (!success)
1301 {
1302 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1303 result.SetStatus(eReturnStatusFailed);
1304 return false;
1305 }
1306 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1307 {
Daniel Malead01b2952012-11-29 21:49:15 +00001308 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 +00001309 result.SetStatus(eReturnStatusFailed);
1310 return false;
1311 }
1312 buffer.PutMaxHex64 (uval64, item_byte_size);
1313 break;
1314
1315 case eFormatOctal:
1316 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1317 if (!success)
1318 {
1319 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1320 result.SetStatus(eReturnStatusFailed);
1321 return false;
1322 }
1323 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1324 {
Daniel Malead01b2952012-11-29 21:49:15 +00001325 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 +00001326 result.SetStatus(eReturnStatusFailed);
1327 return false;
1328 }
1329 buffer.PutMaxHex64 (uval64, item_byte_size);
1330 break;
1331 }
1332 }
1333
1334 if (!buffer.GetString().empty())
1335 {
1336 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001337 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001338 return true;
1339 else
1340 {
Daniel Malead01b2952012-11-29 21:49:15 +00001341 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001342 result.SetStatus(eReturnStatusFailed);
1343 return false;
1344 }
1345 }
1346 return true;
1347 }
1348
Greg Clayton1deb7962011-10-25 06:44:01 +00001349 OptionGroupOptions m_option_group;
1350 OptionGroupFormat m_format_options;
1351 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001352};
1353
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001354
1355//-------------------------------------------------------------------------
1356// CommandObjectMemory
1357//-------------------------------------------------------------------------
1358
Greg Clayton66111032010-06-23 01:19:29 +00001359CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001360 CommandObjectMultiword (interpreter,
1361 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001362 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001363 "memory <subcommand> [<subcommand-options>]")
1364{
Greg Claytona7015092010-09-18 01:14:36 +00001365 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1366 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001367}
1368
1369CommandObjectMemory::~CommandObjectMemory ()
1370{
1371}