blob: 0874f01cf8c89bb186fb35ac73abc5c49b194c59 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "CommandObjectMemory.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/DataExtractor.h"
Greg Clayton63094e02010-06-23 01:19:29 +000018#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000020#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton63094e02010-06-23 01:19:29 +000021#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton63094e02010-06-23 01:19:29 +000023#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/Options.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000025#include "lldb/Interpreter/OptionGroupFormat.h"
26#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton56bbdaf2011-04-28 20:55:26 +000027#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton73844aa2012-08-22 17:17:09 +000028#include "lldb/Interpreter/OptionValueString.h"
Sean Callanan3e80cd92011-10-12 02:08:07 +000029#include "lldb/Symbol/ClangNamespaceDecl.h"
Chris Lattner24943d22010-06-08 16:52:24 +000030#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000031#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000032
33using namespace lldb;
34using namespace lldb_private;
35
Greg Clayton56bbdaf2011-04-28 20:55:26 +000036static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000037g_option_table[] =
38{
Greg Clayton57b3c6b2011-04-27 22:04:39 +000039 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
40 { LLDB_OPT_SET_2, false, "binary" ,'b', no_argument , NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
Sean Callanan8a6f3e92012-04-28 01:27:38 +000041 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
42 { LLDB_OPT_SET_4, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over 1024 bytes of memory."},
Greg Clayton57b3c6b2011-04-27 22:04:39 +000043};
44
45
46
47class OptionGroupReadMemory : public OptionGroup
48{
49public:
50
51 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000052 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000053 m_output_as_binary (false),
54 m_view_as_type()
55 {
56 }
57
58 virtual
59 ~OptionGroupReadMemory ()
60 {
61 }
62
63
64 virtual uint32_t
65 GetNumDefinitions ()
66 {
67 return sizeof (g_option_table) / sizeof (OptionDefinition);
68 }
69
70 virtual const OptionDefinition*
71 GetDefinitions ()
72 {
73 return g_option_table;
74 }
75
76 virtual Error
77 SetOptionValue (CommandInterpreter &interpreter,
78 uint32_t option_idx,
79 const char *option_arg)
80 {
81 Error error;
82 char short_option = (char) g_option_table[option_idx].short_option;
83
84 switch (short_option)
85 {
86 case 'l':
87 error = m_num_per_line.SetValueFromCString (option_arg);
88 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000089 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000090 break;
Greg Claytona42880a2011-10-25 06:44:01 +000091
Greg Clayton57b3c6b2011-04-27 22:04:39 +000092 case 'b':
93 m_output_as_binary = true;
94 break;
95
96 case 't':
97 error = m_view_as_type.SetValueFromCString (option_arg);
98 break;
Sean Callanan8a6f3e92012-04-28 01:27:38 +000099
100 case 'r':
101 m_force = true;
102 break;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000103
104 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000105 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000106 break;
107 }
108 return error;
109 }
110
111 virtual void
112 OptionParsingStarting (CommandInterpreter &interpreter)
113 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000114 m_num_per_line.Clear();
115 m_output_as_binary = false;
116 m_view_as_type.Clear();
117 }
118
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000119 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000120 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000121 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000122 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000123 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
124 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000125 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000126 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000127 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000128
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000129 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000130 {
131 default:
132 break;
133
134 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000135 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000136 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000137 if (!num_per_line_option_set)
138 m_num_per_line = 1;
139 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000140 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000141 break;
142
143 case eFormatCString:
144 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000145
146 case eFormatInstruction:
147 if (count_option_set)
148 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue();
149 m_num_per_line = 1;
150 break;
151
152 case eFormatAddressInfo:
153 if (!byte_size_option_set)
154 byte_size_value = target->GetArchitecture().GetAddressByteSize();
155 m_num_per_line = 1;
156 if (!count_option_set)
157 format_options.GetCountValue() = 8;
158 break;
159
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000160 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000161 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000162 if (!num_per_line_option_set)
163 m_num_per_line = 4;
164 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000165 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000166 break;
167
168 case eFormatBinary:
169 case eFormatFloat:
170 case eFormatOctal:
171 case eFormatDecimal:
172 case eFormatEnum:
173 case eFormatUnicode16:
174 case eFormatUnicode32:
175 case eFormatUnsigned:
Greg Clayton24a6bd92011-10-27 17:55:14 +0000176 case eFormatHexFloat:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000177 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000178 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000179 if (!num_per_line_option_set)
180 m_num_per_line = 1;
181 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000182 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000183 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000184
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000185 case eFormatBytes:
186 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000187 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000188 {
Greg Claytona42880a2011-10-25 06:44:01 +0000189 if (byte_size_value > 1)
Johnny Chenbf9ba592012-03-06 01:17:59 +0000190 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n"
191 "\tconsider using a different display format or don't specify the byte size",
192 byte_size_value.GetCurrentValue());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000193 }
194 else
Greg Claytona42880a2011-10-25 06:44:01 +0000195 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000196 if (!num_per_line_option_set)
197 m_num_per_line = 16;
198 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000199 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000200 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000201 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000202 case eFormatChar:
203 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000204 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000205 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000206 if (!num_per_line_option_set)
207 m_num_per_line = 32;
208 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000209 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000210 break;
211 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000212 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000213 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000214 if (!num_per_line_option_set)
215 m_num_per_line = 1;
216 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000217 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000218 break;
219 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000220 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000221 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000222 if (!num_per_line_option_set)
223 {
Greg Claytona42880a2011-10-25 06:44:01 +0000224 switch (byte_size_value)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000225 {
226 case 1:
227 case 2:
228 m_num_per_line = 8;
229 break;
230 case 4:
231 m_num_per_line = 4;
232 break;
233 case 8:
234 m_num_per_line = 2;
235 break;
236 default:
237 m_num_per_line = 1;
238 break;
239 }
240 }
241 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000242 count_value = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000243 break;
244
245 case eFormatVectorOfChar:
246 case eFormatVectorOfSInt8:
247 case eFormatVectorOfUInt8:
248 case eFormatVectorOfSInt16:
249 case eFormatVectorOfUInt16:
250 case eFormatVectorOfSInt32:
251 case eFormatVectorOfUInt32:
252 case eFormatVectorOfSInt64:
253 case eFormatVectorOfUInt64:
254 case eFormatVectorOfFloat32:
255 case eFormatVectorOfFloat64:
256 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000257 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000258 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000259 if (!num_per_line_option_set)
260 m_num_per_line = 1;
261 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000262 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000263 break;
264 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000265 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000266 }
267
Greg Clayton902b5be2011-10-26 04:32:38 +0000268 bool
269 AnyOptionWasSet () const
270 {
271 return m_num_per_line.OptionWasSet() ||
272 m_output_as_binary ||
273 m_view_as_type.OptionWasSet();
274 }
275
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000276 OptionValueUInt64 m_num_per_line;
277 bool m_output_as_binary;
278 OptionValueString m_view_as_type;
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000279 bool m_force;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000280};
281
282
283
Chris Lattner24943d22010-06-08 16:52:24 +0000284//----------------------------------------------------------------------
285// Read memory from the inferior process
286//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000287class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000288{
289public:
290
Greg Clayton238c0a12010-09-18 01:14:36 +0000291 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000292 CommandObjectParsed (interpreter,
293 "memory read",
294 "Read from the memory of the process being debugged.",
295 NULL,
296 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000297 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000298 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000299 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000300 m_outfile_options (),
Greg Clayton902b5be2011-10-26 04:32:38 +0000301 m_varobj_options(),
302 m_next_addr(LLDB_INVALID_ADDRESS),
303 m_prev_byte_size(0),
304 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
305 m_prev_memory_options (),
306 m_prev_outfile_options (),
307 m_prev_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000308 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000309 CommandArgumentEntry arg1;
310 CommandArgumentEntry arg2;
311 CommandArgumentData start_addr_arg;
312 CommandArgumentData end_addr_arg;
313
314 // Define the first (and only) variant of this arg.
315 start_addr_arg.arg_type = eArgTypeStartAddress;
316 start_addr_arg.arg_repetition = eArgRepeatPlain;
317
318 // There is only one variant this argument could be; put it into the argument entry.
319 arg1.push_back (start_addr_arg);
320
321 // Define the first (and only) variant of this arg.
322 end_addr_arg.arg_type = eArgTypeEndAddress;
323 end_addr_arg.arg_repetition = eArgRepeatOptional;
324
325 // There is only one variant this argument could be; put it into the argument entry.
326 arg2.push_back (end_addr_arg);
327
328 // Push the data for the first argument into the m_arguments vector.
329 m_arguments.push_back (arg1);
330 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000331
Greg Claytona42880a2011-10-25 06:44:01 +0000332 // Add the "--format" and "--count" options to group 1 and 3
333 m_option_group.Append (&m_format_options,
334 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000335 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000336 m_option_group.Append (&m_format_options,
337 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000338 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Claytona42880a2011-10-25 06:44:01 +0000339 // Add the "--size" option to group 1 and 2
340 m_option_group.Append (&m_format_options,
341 OptionGroupFormat::OPTION_GROUP_SIZE,
342 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000343 m_option_group.Append (&m_memory_options);
344 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000345 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000346 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000347 }
348
349 virtual
350 ~CommandObjectMemoryRead ()
351 {
352 }
353
354 Options *
355 GetOptions ()
356 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000357 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000358 }
359
Greg Clayton902b5be2011-10-26 04:32:38 +0000360 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
361 {
362 return m_cmd_name.c_str();
363 }
364
Jim Inghamda26bd22012-06-08 21:56:10 +0000365protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000366 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000367 DoExecute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000368 CommandReturnObject &result)
369 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000370 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000371 Target *target = exe_ctx.GetTargetPtr();
372 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000373 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000374 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000375 result.SetStatus(eReturnStatusFailed);
376 return false;
377 }
378 const size_t argc = command.GetArgumentCount();
379
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000380
Greg Clayton902b5be2011-10-26 04:32:38 +0000381 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000382 {
383 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
384 result.SetStatus(eReturnStatusFailed);
385 return false;
386 }
387
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000388 ClangASTType clang_ast_type;
389 Error error;
390
391 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000392 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
393 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000394 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000395 // We are viewing memory as a type
396 SymbolContext sc;
Greg Claytondc0a38c2012-03-26 23:03:23 +0000397 const bool exact_match = false;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000398 TypeList type_list;
399 uint32_t reference_count = 0;
400 uint32_t pointer_count = 0;
401 size_t idx;
Sean Callananddb2ece2012-07-10 21:24:26 +0000402
403#define ALL_KEYWORDS \
404 KEYWORD("const") \
405 KEYWORD("volatile") \
406 KEYWORD("restrict") \
407 KEYWORD("struct") \
408 KEYWORD("class") \
409 KEYWORD("union")
410
411#define KEYWORD(s) s,
412 static const char *g_keywords[] =
413 {
414 ALL_KEYWORDS
415 };
416#undef KEYWORD
417
418#define KEYWORD(s) (sizeof(s) - 1),
419 static const int g_keyword_lengths[] =
420 {
421 ALL_KEYWORDS
422 };
423#undef KEYWORD
424
425#undef ALL_KEYWORDS
426
427 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000428 std::string type_str(view_as_type_cstr);
429
430 // Remove all instances of g_keywords that are followed by spaces
431 for (size_t i = 0; i < g_num_keywords; ++i)
432 {
433 const char *keyword = g_keywords[i];
Sean Callananddb2ece2012-07-10 21:24:26 +0000434 int keyword_len = g_keyword_lengths[i];
435
436 idx = 0;
437 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000438 {
439 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callananddb2ece2012-07-10 21:24:26 +0000440 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000441 type_str.erase(idx, keyword_len+1);
Sean Callananddb2ece2012-07-10 21:24:26 +0000442 idx = 0;
443 }
444 else
445 {
446 idx += keyword_len;
447 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000448 }
449 }
450 bool done = type_str.empty();
451 //
452 idx = type_str.find_first_not_of (" \t");
453 if (idx > 0 && idx != std::string::npos)
454 type_str.erase (0, idx);
455 while (!done)
456 {
457 // Strip trailing spaces
458 if (type_str.empty())
459 done = true;
460 else
461 {
462 switch (type_str[type_str.size()-1])
463 {
464 case '*':
465 ++pointer_count;
466 // fall through...
467 case ' ':
468 case '\t':
469 type_str.erase(type_str.size()-1);
470 break;
471
472 case '&':
473 if (reference_count == 0)
474 {
475 reference_count = 1;
476 type_str.erase(type_str.size()-1);
477 }
478 else
479 {
480 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
481 result.SetStatus(eReturnStatusFailed);
482 return false;
483 }
484 break;
485
486 default:
487 done = true;
488 break;
489 }
490 }
491 }
492
493 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000494 StackFrame *frame = exe_ctx.GetFramePtr();
495 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000496 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000497 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000498 if (sc.module_sp)
499 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000500 sc.module_sp->FindTypes (sc,
501 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000502 exact_match,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000503 1,
504 type_list);
505 }
506 }
507 if (type_list.GetSize() == 0)
508 {
Greg Clayton9f95fb62012-04-06 17:41:13 +0000509 target->GetImages().FindTypes (sc,
Greg Clayton567e7f32011-09-22 04:58:26 +0000510 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000511 exact_match,
Greg Clayton567e7f32011-09-22 04:58:26 +0000512 1,
513 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000514 }
515
516 if (type_list.GetSize() == 0)
517 {
518 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
519 lookup_type_name.GetCString(),
520 view_as_type_cstr);
521 result.SetStatus(eReturnStatusFailed);
522 return false;
523 }
524
525 TypeSP type_sp (type_list.GetTypeAtIndex(0));
526 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
527
528 while (pointer_count > 0)
529 {
530 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
531 if (pointer_type)
532 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
533 else
534 {
535 result.AppendError ("unable make a pointer type\n");
536 result.SetStatus(eReturnStatusFailed);
537 return false;
538 }
539 --pointer_count;
540 }
541
Greg Claytona42880a2011-10-25 06:44:01 +0000542 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000543
Greg Claytona42880a2011-10-25 06:44:01 +0000544 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000545 {
546 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
547 view_as_type_cstr);
548 result.SetStatus(eReturnStatusFailed);
549 return false;
550 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000551
Greg Claytona42880a2011-10-25 06:44:01 +0000552 if (!m_format_options.GetCountValue().OptionWasSet())
553 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000554 }
555 else
556 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000557 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000558 }
559
560 // Look for invalid combinations of settings
561 if (error.Fail())
562 {
563 result.AppendErrorWithFormat("%s", error.AsCString());
564 result.SetStatus(eReturnStatusFailed);
565 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000566 }
567
Greg Clayton902b5be2011-10-26 04:32:38 +0000568 lldb::addr_t addr;
569 size_t total_byte_size = 0;
570 if (argc == 0)
571 {
572 // Use the last address and byte size and all options as they were
573 // if no options have been set
574 addr = m_next_addr;
575 total_byte_size = m_prev_byte_size;
576 if (!m_format_options.AnyOptionWasSet() &&
577 !m_memory_options.AnyOptionWasSet() &&
578 !m_outfile_options.AnyOptionWasSet() &&
579 !m_varobj_options.AnyOptionWasSet())
580 {
581 m_format_options = m_prev_format_options;
582 m_memory_options = m_prev_memory_options;
583 m_outfile_options = m_prev_outfile_options;
584 m_varobj_options = m_prev_varobj_options;
585 }
586 }
587
Greg Claytona42880a2011-10-25 06:44:01 +0000588 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
589 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000590 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000591
Chris Lattner24943d22010-06-08 16:52:24 +0000592 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000593 {
594 total_byte_size = item_count * item_byte_size;
595 if (total_byte_size == 0)
596 total_byte_size = 32;
597 }
Chris Lattner24943d22010-06-08 16:52:24 +0000598
Greg Clayton902b5be2011-10-26 04:32:38 +0000599 if (argc > 0)
600 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000601
602 if (addr == LLDB_INVALID_ADDRESS)
603 {
604 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
605 result.SetStatus(eReturnStatusFailed);
606 return false;
607 }
608
609 if (argc == 2)
610 {
611 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
612 if (end_addr == LLDB_INVALID_ADDRESS)
613 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000614 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000615 result.SetStatus(eReturnStatusFailed);
616 return false;
617 }
618 else if (end_addr <= addr)
619 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000620 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
Chris Lattner24943d22010-06-08 16:52:24 +0000621 result.SetStatus(eReturnStatusFailed);
622 return false;
623 }
Greg Claytona42880a2011-10-25 06:44:01 +0000624 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000625 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000626 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner24943d22010-06-08 16:52:24 +0000627 result.SetStatus(eReturnStatusFailed);
628 return false;
629 }
630
631 total_byte_size = end_addr - addr;
632 item_count = total_byte_size / item_byte_size;
633 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000634
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000635 if (total_byte_size > 1024 && !m_memory_options.m_force)
636 {
637 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
638 result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
639 return false;
640 }
641
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000642 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000643 size_t bytes_read = 0;
644 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000645 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000646 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000647 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000648 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000649 if (bytes_read == 0)
650 {
Greg Clayton04e6ada2012-05-25 17:05:55 +0000651 const char *error_cstr = error.AsCString();
652 if (error_cstr && error_cstr[0])
653 {
654 result.AppendError(error_cstr);
655 }
656 else
657 {
658 result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr);
659 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000660 result.SetStatus(eReturnStatusFailed);
661 return false;
662 }
663
664 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000665 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
Greg Clayton902b5be2011-10-26 04:32:38 +0000666 else
667 {
668 m_next_addr = addr + bytes_read;
669 m_prev_byte_size = bytes_read;
670 m_prev_format_options = m_format_options;
671 m_prev_memory_options = m_memory_options;
672 m_prev_outfile_options = m_outfile_options;
673 m_prev_varobj_options = m_varobj_options;
674 }
Chris Lattner24943d22010-06-08 16:52:24 +0000675 }
676
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000677 StreamFile outfile_stream;
678 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000679 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
680 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000681 {
682 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000683 outfile_spec.GetPath (path, sizeof(path));
684
685 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
686 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
687 if (append)
688 open_options |= File::eOpenOptionAppend;
689
690 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000691 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000692 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000693 {
694 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
695 if (bytes_written > 0)
696 {
697 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
698 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000699 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000700 path);
701 return true;
702 }
703 else
704 {
705 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
706 result.SetStatus(eReturnStatusFailed);
707 return false;
708 }
709 }
710 else
711 {
712 // We are going to write ASCII to the file just point the
713 // output_stream to our outfile_stream...
714 output_stream = &outfile_stream;
715 }
716 }
717 else
718 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000719 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000720 result.SetStatus(eReturnStatusFailed);
721 return false;
722 }
723 }
724 else
725 {
726 output_stream = &result.GetOutputStream();
727 }
728
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000729
Greg Clayton24a6bd92011-10-27 17:55:14 +0000730 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000731 if (clang_ast_type.GetOpaqueQualType())
732 {
733 for (uint32_t i = 0; i<item_count; ++i)
734 {
735 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000736 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000737 StreamString name_strm;
738 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000739 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000740 name_strm.GetString().c_str(),
741 address,
742 clang_ast_type));
743 if (valobj_sp)
744 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000745 if (format != eFormatDefault)
746 valobj_sp->SetFormat (format);
747
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000748 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000749
Enrico Granata3069c622012-03-01 04:24:26 +0000750 ValueObject::DumpValueObjectOptions options;
751 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
752 .SetMaximumDepth(m_varobj_options.max_depth)
753 .SetShowLocation(m_varobj_options.show_location)
754 .SetShowTypes(m_varobj_options.show_types)
755 .SetUseObjectiveC(m_varobj_options.use_objc)
756 .SetScopeChecked(scope_already_checked)
757 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000758 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000759 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
760 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
761 .SetFormat(format)
762 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000763 ValueObject::DumpValueObject (*output_stream,
764 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000765 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000766 }
767 else
768 {
769 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
770 view_as_type_cstr,
771 name_strm.GetString().c_str());
772 result.SetStatus(eReturnStatusFailed);
773 return false;
774 }
775 }
776 return true;
777 }
778
779 result.SetStatus(eReturnStatusSuccessFinishResult);
780 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000781 target->GetArchitecture().GetByteOrder(),
782 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000783
784
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000785 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000786 uint32_t bytes_dumped = data.Dump (output_stream,
787 0,
788 m_format_options.GetFormat(),
789 item_byte_size,
790 item_count,
791 num_per_line,
792 addr,
793 0,
794 0,
795 exe_scope);
796 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000797 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000798 return true;
799 }
800
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000801 OptionGroupOptions m_option_group;
802 OptionGroupFormat m_format_options;
803 OptionGroupReadMemory m_memory_options;
804 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000805 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000806 lldb::addr_t m_next_addr;
807 lldb::addr_t m_prev_byte_size;
808 OptionGroupFormat m_prev_format_options;
809 OptionGroupReadMemory m_prev_memory_options;
810 OptionGroupOutputFile m_prev_outfile_options;
811 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000812};
813
Greg Claytona42880a2011-10-25 06:44:01 +0000814
815OptionDefinition
816g_memory_write_option_table[] =
817{
818{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
819{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
820};
821
822
Chris Lattner24943d22010-06-08 16:52:24 +0000823//----------------------------------------------------------------------
824// Write memory to the inferior process
825//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000826class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000827{
828public:
829
Greg Claytona42880a2011-10-25 06:44:01 +0000830 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000831 {
832 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000833 OptionGroupWriteMemory () :
834 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000835 {
Chris Lattner24943d22010-06-08 16:52:24 +0000836 }
837
838 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000839 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000840 {
841 }
842
Greg Claytona42880a2011-10-25 06:44:01 +0000843 virtual uint32_t
844 GetNumDefinitions ()
845 {
846 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
847 }
848
849 virtual const OptionDefinition*
850 GetDefinitions ()
851 {
852 return g_memory_write_option_table;
853 }
854
Chris Lattner24943d22010-06-08 16:52:24 +0000855 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000856 SetOptionValue (CommandInterpreter &interpreter,
857 uint32_t option_idx,
858 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000859 {
860 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000861 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
862
Chris Lattner24943d22010-06-08 16:52:24 +0000863 switch (short_option)
864 {
Greg Claytona42880a2011-10-25 06:44:01 +0000865 case 'i':
866 m_infile.SetFile (option_arg, true);
867 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000868 {
Greg Claytona42880a2011-10-25 06:44:01 +0000869 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000870 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000871 }
Greg Claytona42880a2011-10-25 06:44:01 +0000872 break;
873
874 case 'o':
875 {
876 bool success;
877 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
878 if (!success)
879 {
Greg Clayton9c236732011-10-26 00:56:27 +0000880 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000881 }
882 }
883 break;
884
885 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000886 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000887 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000888 }
889 return error;
890 }
Greg Claytona42880a2011-10-25 06:44:01 +0000891
892 virtual void
893 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000894 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000895 m_infile.Clear();
896 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000897 }
898
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000899 FileSpec m_infile;
900 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000901 };
902
Greg Clayton238c0a12010-09-18 01:14:36 +0000903 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000904 CommandObjectParsed (interpreter,
905 "memory write",
906 "Write to the memory of the process being debugged.",
907 NULL,
908 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000909 m_option_group (interpreter),
910 m_format_options (eFormatBytes, 1, UINT64_MAX),
911 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000912 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000913 CommandArgumentEntry arg1;
914 CommandArgumentEntry arg2;
915 CommandArgumentData addr_arg;
916 CommandArgumentData value_arg;
917
918 // Define the first (and only) variant of this arg.
919 addr_arg.arg_type = eArgTypeAddress;
920 addr_arg.arg_repetition = eArgRepeatPlain;
921
922 // There is only one variant this argument could be; put it into the argument entry.
923 arg1.push_back (addr_arg);
924
925 // Define the first (and only) variant of this arg.
926 value_arg.arg_type = eArgTypeValue;
927 value_arg.arg_repetition = eArgRepeatPlus;
928
929 // There is only one variant this argument could be; put it into the argument entry.
930 arg2.push_back (value_arg);
931
932 // Push the data for the first argument into the m_arguments vector.
933 m_arguments.push_back (arg1);
934 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000935
936 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
937 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
938 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
939 m_option_group.Finalize();
940
Chris Lattner24943d22010-06-08 16:52:24 +0000941 }
942
943 virtual
944 ~CommandObjectMemoryWrite ()
945 {
946 }
947
948 Options *
949 GetOptions ()
950 {
Greg Claytona42880a2011-10-25 06:44:01 +0000951 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000952 }
953
954 bool
955 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
956 {
957 if (total_byte_size > 8)
958 return false;
959
960 if (total_byte_size == 8)
961 return true;
962
963 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
964 return uval64 <= max;
965 }
966
967 bool
968 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
969 {
970 if (total_byte_size > 8)
971 return false;
972
973 if (total_byte_size == 8)
974 return true;
975
976 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
977 const int64_t min = ~(max);
978 return min <= sval64 && sval64 <= max;
979 }
980
Jim Inghamda26bd22012-06-08 21:56:10 +0000981protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000982 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000983 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000984 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000985 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000986 if (process == NULL)
987 {
988 result.AppendError("need a process to read memory");
989 result.SetStatus(eReturnStatusFailed);
990 return false;
991 }
992
993 const size_t argc = command.GetArgumentCount();
994
Greg Claytona42880a2011-10-25 06:44:01 +0000995 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000996 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000997 if (argc < 1)
998 {
999 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1000 result.SetStatus(eReturnStatusFailed);
1001 return false;
1002 }
1003 }
1004 else if (argc < 2)
1005 {
1006 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +00001007 result.SetStatus(eReturnStatusFailed);
1008 return false;
1009 }
1010
Chris Lattner24943d22010-06-08 16:52:24 +00001011 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +00001012 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1013 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +00001014
Greg Claytona42880a2011-10-25 06:44:01 +00001015 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1016 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +00001017
Chris Lattner24943d22010-06-08 16:52:24 +00001018 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
1019
1020 if (addr == LLDB_INVALID_ADDRESS)
1021 {
1022 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
1023 result.SetStatus(eReturnStatusFailed);
1024 return false;
1025 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001026
Greg Claytona42880a2011-10-25 06:44:01 +00001027 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001028 {
1029 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +00001030 if (item_byte_size > 0)
1031 length = item_byte_size;
1032 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001033 if (data_sp)
1034 {
1035 length = data_sp->GetByteSize();
1036 if (length > 0)
1037 {
1038 Error error;
1039 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1040
1041 if (bytes_written == length)
1042 {
1043 // All bytes written
1044 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
1045 result.SetStatus(eReturnStatusSuccessFinishResult);
1046 }
1047 else if (bytes_written > 0)
1048 {
1049 // Some byte written
1050 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
1051 result.SetStatus(eReturnStatusSuccessFinishResult);
1052 }
1053 else
1054 {
1055 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1056 result.SetStatus(eReturnStatusFailed);
1057 }
1058 }
1059 }
1060 else
1061 {
1062 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1063 result.SetStatus(eReturnStatusFailed);
1064 }
1065 return result.Succeeded();
1066 }
Greg Claytona42880a2011-10-25 06:44:01 +00001067 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001068 {
Greg Claytona42880a2011-10-25 06:44:01 +00001069 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001070 item_byte_size = buffer.GetAddressByteSize();
1071 else
1072 item_byte_size = 1;
1073 }
1074
Chris Lattner24943d22010-06-08 16:52:24 +00001075 command.Shift(); // shift off the address argument
1076 uint64_t uval64;
1077 int64_t sval64;
1078 bool success = false;
1079 const uint32_t num_value_args = command.GetArgumentCount();
1080 uint32_t i;
1081 for (i=0; i<num_value_args; ++i)
1082 {
1083 const char *value_str = command.GetArgumentAtIndex(i);
1084
Greg Claytona42880a2011-10-25 06:44:01 +00001085 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001086 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001087 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001088 case eFormatFloat: // TODO: add support for floats soon
1089 case eFormatCharPrintable:
1090 case eFormatBytesWithASCII:
1091 case eFormatComplex:
1092 case eFormatEnum:
1093 case eFormatUnicode16:
1094 case eFormatUnicode32:
1095 case eFormatVectorOfChar:
1096 case eFormatVectorOfSInt8:
1097 case eFormatVectorOfUInt8:
1098 case eFormatVectorOfSInt16:
1099 case eFormatVectorOfUInt16:
1100 case eFormatVectorOfSInt32:
1101 case eFormatVectorOfUInt32:
1102 case eFormatVectorOfSInt64:
1103 case eFormatVectorOfUInt64:
1104 case eFormatVectorOfFloat32:
1105 case eFormatVectorOfFloat64:
1106 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001107 case eFormatOSType:
1108 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001109 case eFormatAddressInfo:
1110 case eFormatHexFloat:
1111 case eFormatInstruction:
Sean Callanan96abc622012-08-08 17:35:10 +00001112 case eFormatVoid:
Chris Lattner24943d22010-06-08 16:52:24 +00001113 result.AppendError("unsupported format for writing memory");
1114 result.SetStatus(eReturnStatusFailed);
1115 return false;
1116
1117 case eFormatDefault:
1118 case eFormatBytes:
1119 case eFormatHex:
Enrico Granata535543d2012-08-09 19:33:34 +00001120 case eFormatHexUppercase:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001121 case eFormatPointer:
1122
Chris Lattner24943d22010-06-08 16:52:24 +00001123 // Decode hex bytes
1124 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1125 if (!success)
1126 {
1127 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1128 result.SetStatus(eReturnStatusFailed);
1129 return false;
1130 }
1131 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1132 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001133 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001134 result.SetStatus(eReturnStatusFailed);
1135 return false;
1136 }
1137 buffer.PutMaxHex64 (uval64, item_byte_size);
1138 break;
1139
1140 case eFormatBoolean:
1141 uval64 = Args::StringToBoolean(value_str, false, &success);
1142 if (!success)
1143 {
1144 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1145 result.SetStatus(eReturnStatusFailed);
1146 return false;
1147 }
1148 buffer.PutMaxHex64 (uval64, item_byte_size);
1149 break;
1150
1151 case eFormatBinary:
1152 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1153 if (!success)
1154 {
1155 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1156 result.SetStatus(eReturnStatusFailed);
1157 return false;
1158 }
1159 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1160 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001161 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001162 result.SetStatus(eReturnStatusFailed);
1163 return false;
1164 }
1165 buffer.PutMaxHex64 (uval64, item_byte_size);
1166 break;
1167
Greg Clayton307fa072011-06-17 23:50:44 +00001168 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001169 case eFormatChar:
1170 case eFormatCString:
1171 if (value_str[0])
1172 {
1173 size_t len = strlen (value_str);
1174 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001175 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001176 ++len;
1177 Error error;
1178 if (process->WriteMemory (addr, value_str, len, error) == len)
1179 {
1180 addr += len;
1181 }
1182 else
1183 {
1184 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1185 result.SetStatus(eReturnStatusFailed);
1186 return false;
1187 }
1188 }
1189 break;
1190
1191 case eFormatDecimal:
1192 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1193 if (!success)
1194 {
1195 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1196 result.SetStatus(eReturnStatusFailed);
1197 return false;
1198 }
1199 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1200 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001201 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001202 result.SetStatus(eReturnStatusFailed);
1203 return false;
1204 }
1205 buffer.PutMaxHex64 (sval64, item_byte_size);
1206 break;
1207
1208 case eFormatUnsigned:
1209 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1210 if (!success)
1211 {
1212 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1213 result.SetStatus(eReturnStatusFailed);
1214 return false;
1215 }
1216 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1217 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001218 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001219 result.SetStatus(eReturnStatusFailed);
1220 return false;
1221 }
1222 buffer.PutMaxHex64 (uval64, item_byte_size);
1223 break;
1224
1225 case eFormatOctal:
1226 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1227 if (!success)
1228 {
1229 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1230 result.SetStatus(eReturnStatusFailed);
1231 return false;
1232 }
1233 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1234 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001235 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001236 result.SetStatus(eReturnStatusFailed);
1237 return false;
1238 }
1239 buffer.PutMaxHex64 (uval64, item_byte_size);
1240 break;
1241 }
1242 }
1243
1244 if (!buffer.GetString().empty())
1245 {
1246 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001247 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001248 return true;
1249 else
1250 {
1251 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1252 result.SetStatus(eReturnStatusFailed);
1253 return false;
1254 }
1255 }
1256 return true;
1257 }
1258
Greg Claytona42880a2011-10-25 06:44:01 +00001259 OptionGroupOptions m_option_group;
1260 OptionGroupFormat m_format_options;
1261 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001262};
1263
Chris Lattner24943d22010-06-08 16:52:24 +00001264
1265//-------------------------------------------------------------------------
1266// CommandObjectMemory
1267//-------------------------------------------------------------------------
1268
Greg Clayton63094e02010-06-23 01:19:29 +00001269CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001270 CommandObjectMultiword (interpreter,
1271 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001272 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001273 "memory <subcommand> [<subcommand-options>]")
1274{
Greg Clayton238c0a12010-09-18 01:14:36 +00001275 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1276 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001277}
1278
1279CommandObjectMemory::~CommandObjectMemory ()
1280{
1281}