blob: e804b4a6474604905be93720bca83c8e3c69a4e8 [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) )
Enrico Granata0947a6e2013-10-29 23:04:29 +0000863 && (item_byte_size != 1))
Enrico Granata31898912013-05-21 17:39:04 +0000864 {
Enrico Granata0947a6e2013-10-29 23:04:29 +0000865 // if a count was not passed, or it is 1
866 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
867 {
868 // this turns requests such as
869 // memory read -fc -s10 -c1 *charPtrPtr
870 // which make no sense (what is a char of size 10?)
871 // into a request for fetching 10 chars of size 1 from the same memory location
872 format = eFormatCharArray;
873 item_count = item_byte_size;
874 item_byte_size = 1;
875 }
876 else
877 {
878 // here we passed a count, and it was not 1
879 // so we have a byte_size and a count
880 // we could well multiply those, but instead let's just fail
881 result.AppendErrorWithFormat("reading memory as characters of size %zu is not supported", item_byte_size);
882 result.SetStatus(eReturnStatusFailed);
883 return false;
884 }
Enrico Granata31898912013-05-21 17:39:04 +0000885 }
Greg Clayton84c39662011-04-27 22:04:39 +0000886
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000887 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000888 size_t bytes_dumped = data.Dump (output_stream,
889 0,
Enrico Granata31898912013-05-21 17:39:04 +0000890 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000891 item_byte_size,
892 item_count,
893 num_per_line,
894 addr,
895 0,
896 0,
897 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000898 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000899 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000900 return true;
901 }
902
Greg Clayton84c39662011-04-27 22:04:39 +0000903 OptionGroupOptions m_option_group;
904 OptionGroupFormat m_format_options;
905 OptionGroupReadMemory m_memory_options;
906 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000907 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000908 lldb::addr_t m_next_addr;
909 lldb::addr_t m_prev_byte_size;
910 OptionGroupFormat m_prev_format_options;
911 OptionGroupReadMemory m_prev_memory_options;
912 OptionGroupOutputFile m_prev_outfile_options;
913 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000914 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000915};
916
Greg Clayton1deb7962011-10-25 06:44:01 +0000917
918OptionDefinition
919g_memory_write_option_table[] =
920{
Virgile Belloe2607b52013-09-05 16:42:23 +0000921{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
922{ 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 +0000923};
924
925
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000926//----------------------------------------------------------------------
927// Write memory to the inferior process
928//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000929class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000930{
931public:
932
Greg Clayton1deb7962011-10-25 06:44:01 +0000933 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000934 {
935 public:
Greg Clayton1deb7962011-10-25 06:44:01 +0000936 OptionGroupWriteMemory () :
937 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000938 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000939 }
940
941 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +0000942 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000943 {
944 }
945
Greg Clayton1deb7962011-10-25 06:44:01 +0000946 virtual uint32_t
947 GetNumDefinitions ()
948 {
949 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
950 }
951
952 virtual const OptionDefinition*
953 GetDefinitions ()
954 {
955 return g_memory_write_option_table;
956 }
957
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000958 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000959 SetOptionValue (CommandInterpreter &interpreter,
960 uint32_t option_idx,
961 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000962 {
963 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000964 const int short_option = g_memory_write_option_table[option_idx].short_option;
Greg Clayton1deb7962011-10-25 06:44:01 +0000965
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000966 switch (short_option)
967 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000968 case 'i':
969 m_infile.SetFile (option_arg, true);
970 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000971 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000972 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +0000973 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000974 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000975 break;
976
977 case 'o':
978 {
979 bool success;
980 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
981 if (!success)
982 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000983 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +0000984 }
985 }
986 break;
987
988 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000989 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +0000990 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000991 }
992 return error;
993 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000994
995 virtual void
996 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000997 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000998 m_infile.Clear();
999 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001000 }
1001
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001002 FileSpec m_infile;
1003 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001004 };
1005
Greg Claytona7015092010-09-18 01:14:36 +00001006 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001007 CommandObjectParsed (interpreter,
1008 "memory write",
1009 "Write to the memory of the process being debugged.",
1010 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +00001011 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001012 m_option_group (interpreter),
1013 m_format_options (eFormatBytes, 1, UINT64_MAX),
1014 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001015 {
Caroline Tice405fe672010-10-04 22:28:36 +00001016 CommandArgumentEntry arg1;
1017 CommandArgumentEntry arg2;
1018 CommandArgumentData addr_arg;
1019 CommandArgumentData value_arg;
1020
1021 // Define the first (and only) variant of this arg.
1022 addr_arg.arg_type = eArgTypeAddress;
1023 addr_arg.arg_repetition = eArgRepeatPlain;
1024
1025 // There is only one variant this argument could be; put it into the argument entry.
1026 arg1.push_back (addr_arg);
1027
1028 // Define the first (and only) variant of this arg.
1029 value_arg.arg_type = eArgTypeValue;
1030 value_arg.arg_repetition = eArgRepeatPlus;
1031
1032 // There is only one variant this argument could be; put it into the argument entry.
1033 arg2.push_back (value_arg);
1034
1035 // Push the data for the first argument into the m_arguments vector.
1036 m_arguments.push_back (arg1);
1037 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001038
1039 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1040 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1041 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1042 m_option_group.Finalize();
1043
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001044 }
1045
1046 virtual
1047 ~CommandObjectMemoryWrite ()
1048 {
1049 }
1050
1051 Options *
1052 GetOptions ()
1053 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001054 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001055 }
1056
1057 bool
1058 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1059 {
1060 if (total_byte_size > 8)
1061 return false;
1062
1063 if (total_byte_size == 8)
1064 return true;
1065
1066 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1067 return uval64 <= max;
1068 }
1069
1070 bool
1071 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1072 {
1073 if (total_byte_size > 8)
1074 return false;
1075
1076 if (total_byte_size == 8)
1077 return true;
1078
1079 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1080 const int64_t min = ~(max);
1081 return min <= sval64 && sval64 <= max;
1082 }
1083
Jim Ingham5a988412012-06-08 21:56:10 +00001084protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001085 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001086 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001087 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001088 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1089 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001090
1091 const size_t argc = command.GetArgumentCount();
1092
Greg Clayton1deb7962011-10-25 06:44:01 +00001093 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001094 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001095 if (argc < 1)
1096 {
1097 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1098 result.SetStatus(eReturnStatusFailed);
1099 return false;
1100 }
1101 }
1102 else if (argc < 2)
1103 {
1104 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 +00001105 result.SetStatus(eReturnStatusFailed);
1106 return false;
1107 }
1108
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001109 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001110 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1111 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001112
Greg Clayton1deb7962011-10-25 06:44:01 +00001113 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1114 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001115
Greg Claytonb9d5df52012-12-06 22:49:16 +00001116 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001117 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001118 command.GetArgumentAtIndex(0),
1119 LLDB_INVALID_ADDRESS,
1120 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001121
1122 if (addr == LLDB_INVALID_ADDRESS)
1123 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001124 result.AppendError("invalid address expression\n");
1125 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001126 result.SetStatus(eReturnStatusFailed);
1127 return false;
1128 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001129
Greg Clayton1deb7962011-10-25 06:44:01 +00001130 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001131 {
1132 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +00001133 if (item_byte_size > 0)
1134 length = item_byte_size;
1135 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001136 if (data_sp)
1137 {
1138 length = data_sp->GetByteSize();
1139 if (length > 0)
1140 {
1141 Error error;
1142 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1143
1144 if (bytes_written == length)
1145 {
1146 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001147 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001148 result.SetStatus(eReturnStatusSuccessFinishResult);
1149 }
1150 else if (bytes_written > 0)
1151 {
1152 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001153 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 +00001154 result.SetStatus(eReturnStatusSuccessFinishResult);
1155 }
1156 else
1157 {
Daniel Malead01b2952012-11-29 21:49:15 +00001158 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001159 result.SetStatus(eReturnStatusFailed);
1160 }
1161 }
1162 }
1163 else
1164 {
1165 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1166 result.SetStatus(eReturnStatusFailed);
1167 }
1168 return result.Succeeded();
1169 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001170 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001171 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001172 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001173 item_byte_size = buffer.GetAddressByteSize();
1174 else
1175 item_byte_size = 1;
1176 }
1177
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001178 command.Shift(); // shift off the address argument
1179 uint64_t uval64;
1180 int64_t sval64;
1181 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001182 const size_t num_value_args = command.GetArgumentCount();
1183 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001184 {
1185 const char *value_str = command.GetArgumentAtIndex(i);
1186
Greg Clayton1deb7962011-10-25 06:44:01 +00001187 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001188 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001189 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001190 case eFormatFloat: // TODO: add support for floats soon
1191 case eFormatCharPrintable:
1192 case eFormatBytesWithASCII:
1193 case eFormatComplex:
1194 case eFormatEnum:
1195 case eFormatUnicode16:
1196 case eFormatUnicode32:
1197 case eFormatVectorOfChar:
1198 case eFormatVectorOfSInt8:
1199 case eFormatVectorOfUInt8:
1200 case eFormatVectorOfSInt16:
1201 case eFormatVectorOfUInt16:
1202 case eFormatVectorOfSInt32:
1203 case eFormatVectorOfUInt32:
1204 case eFormatVectorOfSInt64:
1205 case eFormatVectorOfUInt64:
1206 case eFormatVectorOfFloat32:
1207 case eFormatVectorOfFloat64:
1208 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001209 case eFormatOSType:
1210 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001211 case eFormatAddressInfo:
1212 case eFormatHexFloat:
1213 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001214 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001215 result.AppendError("unsupported format for writing memory");
1216 result.SetStatus(eReturnStatusFailed);
1217 return false;
1218
1219 case eFormatDefault:
1220 case eFormatBytes:
1221 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001222 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001223 case eFormatPointer:
1224
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001225 // Decode hex bytes
1226 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1227 if (!success)
1228 {
1229 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1230 result.SetStatus(eReturnStatusFailed);
1231 return false;
1232 }
1233 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1234 {
Daniel Malead01b2952012-11-29 21:49:15 +00001235 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 +00001236 result.SetStatus(eReturnStatusFailed);
1237 return false;
1238 }
1239 buffer.PutMaxHex64 (uval64, item_byte_size);
1240 break;
1241
1242 case eFormatBoolean:
1243 uval64 = Args::StringToBoolean(value_str, false, &success);
1244 if (!success)
1245 {
1246 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1247 result.SetStatus(eReturnStatusFailed);
1248 return false;
1249 }
1250 buffer.PutMaxHex64 (uval64, item_byte_size);
1251 break;
1252
1253 case eFormatBinary:
1254 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1255 if (!success)
1256 {
1257 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1258 result.SetStatus(eReturnStatusFailed);
1259 return false;
1260 }
1261 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1262 {
Daniel Malead01b2952012-11-29 21:49:15 +00001263 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 +00001264 result.SetStatus(eReturnStatusFailed);
1265 return false;
1266 }
1267 buffer.PutMaxHex64 (uval64, item_byte_size);
1268 break;
1269
Greg Clayton4e4294b2011-06-17 23:50:44 +00001270 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001271 case eFormatChar:
1272 case eFormatCString:
1273 if (value_str[0])
1274 {
1275 size_t len = strlen (value_str);
1276 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001277 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001278 ++len;
1279 Error error;
1280 if (process->WriteMemory (addr, value_str, len, error) == len)
1281 {
1282 addr += len;
1283 }
1284 else
1285 {
Daniel Malead01b2952012-11-29 21:49:15 +00001286 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001287 result.SetStatus(eReturnStatusFailed);
1288 return false;
1289 }
1290 }
1291 break;
1292
1293 case eFormatDecimal:
1294 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1295 if (!success)
1296 {
1297 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1298 result.SetStatus(eReturnStatusFailed);
1299 return false;
1300 }
1301 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1302 {
Daniel Malead01b2952012-11-29 21:49:15 +00001303 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 +00001304 result.SetStatus(eReturnStatusFailed);
1305 return false;
1306 }
1307 buffer.PutMaxHex64 (sval64, item_byte_size);
1308 break;
1309
1310 case eFormatUnsigned:
1311 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1312 if (!success)
1313 {
1314 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1315 result.SetStatus(eReturnStatusFailed);
1316 return false;
1317 }
1318 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1319 {
Daniel Malead01b2952012-11-29 21:49:15 +00001320 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 +00001321 result.SetStatus(eReturnStatusFailed);
1322 return false;
1323 }
1324 buffer.PutMaxHex64 (uval64, item_byte_size);
1325 break;
1326
1327 case eFormatOctal:
1328 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1329 if (!success)
1330 {
1331 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1332 result.SetStatus(eReturnStatusFailed);
1333 return false;
1334 }
1335 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1336 {
Daniel Malead01b2952012-11-29 21:49:15 +00001337 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 +00001338 result.SetStatus(eReturnStatusFailed);
1339 return false;
1340 }
1341 buffer.PutMaxHex64 (uval64, item_byte_size);
1342 break;
1343 }
1344 }
1345
1346 if (!buffer.GetString().empty())
1347 {
1348 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001349 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001350 return true;
1351 else
1352 {
Daniel Malead01b2952012-11-29 21:49:15 +00001353 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001354 result.SetStatus(eReturnStatusFailed);
1355 return false;
1356 }
1357 }
1358 return true;
1359 }
1360
Greg Clayton1deb7962011-10-25 06:44:01 +00001361 OptionGroupOptions m_option_group;
1362 OptionGroupFormat m_format_options;
1363 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001364};
1365
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001366
1367//-------------------------------------------------------------------------
1368// CommandObjectMemory
1369//-------------------------------------------------------------------------
1370
Greg Clayton66111032010-06-23 01:19:29 +00001371CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001372 CommandObjectMultiword (interpreter,
1373 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001374 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001375 "memory <subcommand> [<subcommand-options>]")
1376{
Greg Claytona7015092010-09-18 01:14:36 +00001377 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1378 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001379}
1380
1381CommandObjectMemory::~CommandObjectMemory ()
1382{
1383}