blob: fffbda1d1430aa76f4f32f8015fc14aa7d7298d4 [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"
Greg Clayton49ce8962012-08-29 21:13:06 +000019#include "lldb/Core/Module.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Core/StreamString.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000021#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton63094e02010-06-23 01:19:29 +000022#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton63094e02010-06-23 01:19:29 +000024#include "lldb/Interpreter/CommandInterpreter.h"
25#include "lldb/Interpreter/Options.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000026#include "lldb/Interpreter/OptionGroupFormat.h"
27#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton56bbdaf2011-04-28 20:55:26 +000028#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton73844aa2012-08-22 17:17:09 +000029#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000030#include "lldb/Symbol/TypeList.h"
Chris Lattner24943d22010-06-08 16:52:24 +000031#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000032#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000033
34using namespace lldb;
35using namespace lldb_private;
36
Greg Clayton56bbdaf2011-04-28 20:55:26 +000037static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000038g_option_table[] =
39{
Greg Clayton57b3c6b2011-04-27 22:04:39 +000040 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
41 { 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 Callanan06dc17f2012-09-24 22:25:51 +000042 { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton827baf62012-11-02 21:14:58 +000043 { LLDB_OPT_SET_1|
44 LLDB_OPT_SET_2|
45 LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over 1024 bytes of memory."},
Greg Clayton57b3c6b2011-04-27 22:04:39 +000046};
47
48
49
50class OptionGroupReadMemory : public OptionGroup
51{
52public:
53
54 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000055 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000056 m_output_as_binary (false),
57 m_view_as_type()
58 {
59 }
60
61 virtual
62 ~OptionGroupReadMemory ()
63 {
64 }
65
66
67 virtual uint32_t
68 GetNumDefinitions ()
69 {
70 return sizeof (g_option_table) / sizeof (OptionDefinition);
71 }
72
73 virtual const OptionDefinition*
74 GetDefinitions ()
75 {
76 return g_option_table;
77 }
78
79 virtual Error
80 SetOptionValue (CommandInterpreter &interpreter,
81 uint32_t option_idx,
82 const char *option_arg)
83 {
84 Error error;
85 char short_option = (char) g_option_table[option_idx].short_option;
86
87 switch (short_option)
88 {
89 case 'l':
90 error = m_num_per_line.SetValueFromCString (option_arg);
91 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000092 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000093 break;
Greg Claytona42880a2011-10-25 06:44:01 +000094
Greg Clayton57b3c6b2011-04-27 22:04:39 +000095 case 'b':
96 m_output_as_binary = true;
97 break;
98
99 case 't':
100 error = m_view_as_type.SetValueFromCString (option_arg);
101 break;
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000102
103 case 'r':
104 m_force = true;
105 break;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000106
107 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000108 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000109 break;
110 }
111 return error;
112 }
113
114 virtual void
115 OptionParsingStarting (CommandInterpreter &interpreter)
116 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000117 m_num_per_line.Clear();
118 m_output_as_binary = false;
119 m_view_as_type.Clear();
120 }
121
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000122 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000123 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000124 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000125 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000126 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
127 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000128 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000129 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000130 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000131
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000132 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000133 {
134 default:
135 break;
136
137 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000138 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000139 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000140 if (!num_per_line_option_set)
141 m_num_per_line = 1;
142 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000143 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000144 break;
145
146 case eFormatCString:
147 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000148
149 case eFormatInstruction:
150 if (count_option_set)
Jim Inghamab885832012-11-07 01:52:04 +0000151 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton24a6bd92011-10-27 17:55:14 +0000152 m_num_per_line = 1;
153 break;
154
155 case eFormatAddressInfo:
156 if (!byte_size_option_set)
157 byte_size_value = target->GetArchitecture().GetAddressByteSize();
158 m_num_per_line = 1;
159 if (!count_option_set)
160 format_options.GetCountValue() = 8;
161 break;
162
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000163 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000164 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000165 if (!num_per_line_option_set)
166 m_num_per_line = 4;
167 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000168 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000169 break;
170
171 case eFormatBinary:
172 case eFormatFloat:
173 case eFormatOctal:
174 case eFormatDecimal:
175 case eFormatEnum:
176 case eFormatUnicode16:
177 case eFormatUnicode32:
178 case eFormatUnsigned:
Greg Clayton24a6bd92011-10-27 17:55:14 +0000179 case eFormatHexFloat:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000180 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000181 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000182 if (!num_per_line_option_set)
183 m_num_per_line = 1;
184 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000185 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000186 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000187
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000188 case eFormatBytes:
189 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000190 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000191 {
Greg Claytona42880a2011-10-25 06:44:01 +0000192 if (byte_size_value > 1)
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000193 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenbf9ba592012-03-06 01:17:59 +0000194 "\tconsider using a different display format or don't specify the byte size",
195 byte_size_value.GetCurrentValue());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000196 }
197 else
Greg Claytona42880a2011-10-25 06:44:01 +0000198 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000199 if (!num_per_line_option_set)
200 m_num_per_line = 16;
201 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000202 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000203 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000204 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000205 case eFormatChar:
206 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000207 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000208 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000209 if (!num_per_line_option_set)
210 m_num_per_line = 32;
211 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000212 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000213 break;
214 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000215 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000216 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000217 if (!num_per_line_option_set)
218 m_num_per_line = 1;
219 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000220 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000221 break;
222 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000223 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000224 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000225 if (!num_per_line_option_set)
226 {
Greg Claytona42880a2011-10-25 06:44:01 +0000227 switch (byte_size_value)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000228 {
229 case 1:
230 case 2:
231 m_num_per_line = 8;
232 break;
233 case 4:
234 m_num_per_line = 4;
235 break;
236 case 8:
237 m_num_per_line = 2;
238 break;
239 default:
240 m_num_per_line = 1;
241 break;
242 }
243 }
244 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000245 count_value = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000246 break;
247
248 case eFormatVectorOfChar:
249 case eFormatVectorOfSInt8:
250 case eFormatVectorOfUInt8:
251 case eFormatVectorOfSInt16:
252 case eFormatVectorOfUInt16:
253 case eFormatVectorOfSInt32:
254 case eFormatVectorOfUInt32:
255 case eFormatVectorOfSInt64:
256 case eFormatVectorOfUInt64:
257 case eFormatVectorOfFloat32:
258 case eFormatVectorOfFloat64:
259 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000260 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000261 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000262 if (!num_per_line_option_set)
263 m_num_per_line = 1;
264 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000265 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000266 break;
267 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000268 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000269 }
270
Greg Clayton902b5be2011-10-26 04:32:38 +0000271 bool
272 AnyOptionWasSet () const
273 {
274 return m_num_per_line.OptionWasSet() ||
275 m_output_as_binary ||
276 m_view_as_type.OptionWasSet();
277 }
278
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000279 OptionValueUInt64 m_num_per_line;
280 bool m_output_as_binary;
281 OptionValueString m_view_as_type;
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000282 bool m_force;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000283};
284
285
286
Chris Lattner24943d22010-06-08 16:52:24 +0000287//----------------------------------------------------------------------
288// Read memory from the inferior process
289//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000290class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000291{
292public:
293
Greg Clayton238c0a12010-09-18 01:14:36 +0000294 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000295 CommandObjectParsed (interpreter,
296 "memory read",
297 "Read from the memory of the process being debugged.",
298 NULL,
299 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000300 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000301 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000302 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000303 m_outfile_options (),
Greg Clayton902b5be2011-10-26 04:32:38 +0000304 m_varobj_options(),
305 m_next_addr(LLDB_INVALID_ADDRESS),
306 m_prev_byte_size(0),
307 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
308 m_prev_memory_options (),
309 m_prev_outfile_options (),
310 m_prev_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000311 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000312 CommandArgumentEntry arg1;
313 CommandArgumentEntry arg2;
314 CommandArgumentData start_addr_arg;
315 CommandArgumentData end_addr_arg;
316
317 // Define the first (and only) variant of this arg.
318 start_addr_arg.arg_type = eArgTypeStartAddress;
319 start_addr_arg.arg_repetition = eArgRepeatPlain;
320
321 // There is only one variant this argument could be; put it into the argument entry.
322 arg1.push_back (start_addr_arg);
323
324 // Define the first (and only) variant of this arg.
325 end_addr_arg.arg_type = eArgTypeEndAddress;
326 end_addr_arg.arg_repetition = eArgRepeatOptional;
327
328 // There is only one variant this argument could be; put it into the argument entry.
329 arg2.push_back (end_addr_arg);
330
331 // Push the data for the first argument into the m_arguments vector.
332 m_arguments.push_back (arg1);
333 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000334
Greg Claytona42880a2011-10-25 06:44:01 +0000335 // Add the "--format" and "--count" options to group 1 and 3
336 m_option_group.Append (&m_format_options,
337 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000338 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000339 m_option_group.Append (&m_format_options,
340 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000341 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Claytona42880a2011-10-25 06:44:01 +0000342 // Add the "--size" option to group 1 and 2
343 m_option_group.Append (&m_format_options,
344 OptionGroupFormat::OPTION_GROUP_SIZE,
345 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000346 m_option_group.Append (&m_memory_options);
347 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 +0000348 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000349 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000350 }
351
352 virtual
353 ~CommandObjectMemoryRead ()
354 {
355 }
356
357 Options *
358 GetOptions ()
359 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000360 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000361 }
362
Greg Clayton902b5be2011-10-26 04:32:38 +0000363 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
364 {
365 return m_cmd_name.c_str();
366 }
367
Jim Inghamda26bd22012-06-08 21:56:10 +0000368protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000369 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000370 DoExecute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000371 CommandReturnObject &result)
372 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000373 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000374 Target *target = exe_ctx.GetTargetPtr();
375 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000376 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000377 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000378 result.SetStatus(eReturnStatusFailed);
379 return false;
380 }
381 const size_t argc = command.GetArgumentCount();
382
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000383
Greg Clayton902b5be2011-10-26 04:32:38 +0000384 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000385 {
386 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
387 result.SetStatus(eReturnStatusFailed);
388 return false;
389 }
390
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000391 ClangASTType clang_ast_type;
392 Error error;
393
394 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000395 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
396 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000397 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000398 // We are viewing memory as a type
399 SymbolContext sc;
Greg Claytondc0a38c2012-03-26 23:03:23 +0000400 const bool exact_match = false;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000401 TypeList type_list;
402 uint32_t reference_count = 0;
403 uint32_t pointer_count = 0;
404 size_t idx;
Sean Callananddb2ece2012-07-10 21:24:26 +0000405
406#define ALL_KEYWORDS \
407 KEYWORD("const") \
408 KEYWORD("volatile") \
409 KEYWORD("restrict") \
410 KEYWORD("struct") \
411 KEYWORD("class") \
412 KEYWORD("union")
413
414#define KEYWORD(s) s,
415 static const char *g_keywords[] =
416 {
417 ALL_KEYWORDS
418 };
419#undef KEYWORD
420
421#define KEYWORD(s) (sizeof(s) - 1),
422 static const int g_keyword_lengths[] =
423 {
424 ALL_KEYWORDS
425 };
426#undef KEYWORD
427
428#undef ALL_KEYWORDS
429
430 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000431 std::string type_str(view_as_type_cstr);
432
433 // Remove all instances of g_keywords that are followed by spaces
434 for (size_t i = 0; i < g_num_keywords; ++i)
435 {
436 const char *keyword = g_keywords[i];
Sean Callananddb2ece2012-07-10 21:24:26 +0000437 int keyword_len = g_keyword_lengths[i];
438
439 idx = 0;
440 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000441 {
442 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callananddb2ece2012-07-10 21:24:26 +0000443 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000444 type_str.erase(idx, keyword_len+1);
Sean Callananddb2ece2012-07-10 21:24:26 +0000445 idx = 0;
446 }
447 else
448 {
449 idx += keyword_len;
450 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000451 }
452 }
453 bool done = type_str.empty();
454 //
455 idx = type_str.find_first_not_of (" \t");
456 if (idx > 0 && idx != std::string::npos)
457 type_str.erase (0, idx);
458 while (!done)
459 {
460 // Strip trailing spaces
461 if (type_str.empty())
462 done = true;
463 else
464 {
465 switch (type_str[type_str.size()-1])
466 {
467 case '*':
468 ++pointer_count;
469 // fall through...
470 case ' ':
471 case '\t':
472 type_str.erase(type_str.size()-1);
473 break;
474
475 case '&':
476 if (reference_count == 0)
477 {
478 reference_count = 1;
479 type_str.erase(type_str.size()-1);
480 }
481 else
482 {
483 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
484 result.SetStatus(eReturnStatusFailed);
485 return false;
486 }
487 break;
488
489 default:
490 done = true;
491 break;
492 }
493 }
494 }
495
496 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000497 StackFrame *frame = exe_ctx.GetFramePtr();
498 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000499 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000500 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000501 if (sc.module_sp)
502 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000503 sc.module_sp->FindTypes (sc,
504 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000505 exact_match,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000506 1,
507 type_list);
508 }
509 }
510 if (type_list.GetSize() == 0)
511 {
Greg Clayton9f95fb62012-04-06 17:41:13 +0000512 target->GetImages().FindTypes (sc,
Greg Clayton567e7f32011-09-22 04:58:26 +0000513 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000514 exact_match,
Greg Clayton567e7f32011-09-22 04:58:26 +0000515 1,
516 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000517 }
518
519 if (type_list.GetSize() == 0)
520 {
521 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
522 lookup_type_name.GetCString(),
523 view_as_type_cstr);
524 result.SetStatus(eReturnStatusFailed);
525 return false;
526 }
527
528 TypeSP type_sp (type_list.GetTypeAtIndex(0));
529 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
530
531 while (pointer_count > 0)
532 {
533 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
534 if (pointer_type)
535 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
536 else
537 {
538 result.AppendError ("unable make a pointer type\n");
539 result.SetStatus(eReturnStatusFailed);
540 return false;
541 }
542 --pointer_count;
543 }
544
Greg Claytona42880a2011-10-25 06:44:01 +0000545 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000546
Greg Claytona42880a2011-10-25 06:44:01 +0000547 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000548 {
549 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
550 view_as_type_cstr);
551 result.SetStatus(eReturnStatusFailed);
552 return false;
553 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000554
Greg Claytona42880a2011-10-25 06:44:01 +0000555 if (!m_format_options.GetCountValue().OptionWasSet())
556 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000557 }
558 else
559 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000560 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000561 }
562
563 // Look for invalid combinations of settings
564 if (error.Fail())
565 {
566 result.AppendErrorWithFormat("%s", error.AsCString());
567 result.SetStatus(eReturnStatusFailed);
568 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000569 }
570
Greg Clayton902b5be2011-10-26 04:32:38 +0000571 lldb::addr_t addr;
572 size_t total_byte_size = 0;
573 if (argc == 0)
574 {
575 // Use the last address and byte size and all options as they were
576 // if no options have been set
577 addr = m_next_addr;
578 total_byte_size = m_prev_byte_size;
579 if (!m_format_options.AnyOptionWasSet() &&
580 !m_memory_options.AnyOptionWasSet() &&
581 !m_outfile_options.AnyOptionWasSet() &&
582 !m_varobj_options.AnyOptionWasSet())
583 {
584 m_format_options = m_prev_format_options;
585 m_memory_options = m_prev_memory_options;
586 m_outfile_options = m_prev_outfile_options;
587 m_varobj_options = m_prev_varobj_options;
588 }
589 }
590
Greg Claytona42880a2011-10-25 06:44:01 +0000591 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
592 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000593 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000594
Chris Lattner24943d22010-06-08 16:52:24 +0000595 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000596 {
597 total_byte_size = item_count * item_byte_size;
598 if (total_byte_size == 0)
599 total_byte_size = 32;
600 }
Chris Lattner24943d22010-06-08 16:52:24 +0000601
Greg Clayton902b5be2011-10-26 04:32:38 +0000602 if (argc > 0)
603 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000604
605 if (addr == LLDB_INVALID_ADDRESS)
606 {
607 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
608 result.SetStatus(eReturnStatusFailed);
609 return false;
610 }
611
612 if (argc == 2)
613 {
614 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
615 if (end_addr == LLDB_INVALID_ADDRESS)
616 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000617 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000618 result.SetStatus(eReturnStatusFailed);
619 return false;
620 }
621 else if (end_addr <= addr)
622 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000623 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
Chris Lattner24943d22010-06-08 16:52:24 +0000624 result.SetStatus(eReturnStatusFailed);
625 return false;
626 }
Greg Claytona42880a2011-10-25 06:44:01 +0000627 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000628 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000629 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner24943d22010-06-08 16:52:24 +0000630 result.SetStatus(eReturnStatusFailed);
631 return false;
632 }
633
634 total_byte_size = end_addr - addr;
635 item_count = total_byte_size / item_byte_size;
636 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000637
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000638 if (total_byte_size > 1024 && !m_memory_options.m_force)
639 {
640 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
641 result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
642 return false;
643 }
644
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000645 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000646 size_t bytes_read = 0;
647 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000648 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000649 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000650 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000651 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000652 if (bytes_read == 0)
653 {
Greg Clayton04e6ada2012-05-25 17:05:55 +0000654 const char *error_cstr = error.AsCString();
655 if (error_cstr && error_cstr[0])
656 {
657 result.AppendError(error_cstr);
658 }
659 else
660 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000661 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton04e6ada2012-05-25 17:05:55 +0000662 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000663 result.SetStatus(eReturnStatusFailed);
664 return false;
665 }
666
667 if (bytes_read < total_byte_size)
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000668 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
Greg Clayton902b5be2011-10-26 04:32:38 +0000669 else
670 {
671 m_next_addr = addr + bytes_read;
672 m_prev_byte_size = bytes_read;
673 m_prev_format_options = m_format_options;
674 m_prev_memory_options = m_memory_options;
675 m_prev_outfile_options = m_outfile_options;
676 m_prev_varobj_options = m_varobj_options;
677 }
Chris Lattner24943d22010-06-08 16:52:24 +0000678 }
679
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000680 StreamFile outfile_stream;
681 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000682 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
683 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000684 {
685 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000686 outfile_spec.GetPath (path, sizeof(path));
687
688 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
689 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
690 if (append)
691 open_options |= File::eOpenOptionAppend;
692
693 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000694 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000695 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000696 {
697 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
698 if (bytes_written > 0)
699 {
700 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
701 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000702 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000703 path);
704 return true;
705 }
706 else
707 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000708 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000709 result.SetStatus(eReturnStatusFailed);
710 return false;
711 }
712 }
713 else
714 {
715 // We are going to write ASCII to the file just point the
716 // output_stream to our outfile_stream...
717 output_stream = &outfile_stream;
718 }
719 }
720 else
721 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000722 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000723 result.SetStatus(eReturnStatusFailed);
724 return false;
725 }
726 }
727 else
728 {
729 output_stream = &result.GetOutputStream();
730 }
731
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000732
Greg Clayton24a6bd92011-10-27 17:55:14 +0000733 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000734 if (clang_ast_type.GetOpaqueQualType())
735 {
736 for (uint32_t i = 0; i<item_count; ++i)
737 {
738 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000739 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000740 StreamString name_strm;
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000741 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000742 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000743 name_strm.GetString().c_str(),
744 address,
745 clang_ast_type));
746 if (valobj_sp)
747 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000748 if (format != eFormatDefault)
749 valobj_sp->SetFormat (format);
750
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000751 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000752
Enrico Granata3069c622012-03-01 04:24:26 +0000753 ValueObject::DumpValueObjectOptions options;
754 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
755 .SetMaximumDepth(m_varobj_options.max_depth)
756 .SetShowLocation(m_varobj_options.show_location)
757 .SetShowTypes(m_varobj_options.show_types)
758 .SetUseObjectiveC(m_varobj_options.use_objc)
759 .SetScopeChecked(scope_already_checked)
760 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000761 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000762 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
763 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
764 .SetFormat(format)
765 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000766 ValueObject::DumpValueObject (*output_stream,
767 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000768 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000769 }
770 else
771 {
772 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
773 view_as_type_cstr,
774 name_strm.GetString().c_str());
775 result.SetStatus(eReturnStatusFailed);
776 return false;
777 }
778 }
779 return true;
780 }
781
782 result.SetStatus(eReturnStatusSuccessFinishResult);
783 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000784 target->GetArchitecture().GetByteOrder(),
785 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000786
787
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000788 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000789 uint32_t bytes_dumped = data.Dump (output_stream,
790 0,
791 m_format_options.GetFormat(),
792 item_byte_size,
793 item_count,
794 num_per_line,
795 addr,
796 0,
797 0,
798 exe_scope);
799 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000800 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000801 return true;
802 }
803
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000804 OptionGroupOptions m_option_group;
805 OptionGroupFormat m_format_options;
806 OptionGroupReadMemory m_memory_options;
807 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000808 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000809 lldb::addr_t m_next_addr;
810 lldb::addr_t m_prev_byte_size;
811 OptionGroupFormat m_prev_format_options;
812 OptionGroupReadMemory m_prev_memory_options;
813 OptionGroupOutputFile m_prev_outfile_options;
814 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000815};
816
Greg Claytona42880a2011-10-25 06:44:01 +0000817
818OptionDefinition
819g_memory_write_option_table[] =
820{
821{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
822{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
823};
824
825
Chris Lattner24943d22010-06-08 16:52:24 +0000826//----------------------------------------------------------------------
827// Write memory to the inferior process
828//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000829class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000830{
831public:
832
Greg Claytona42880a2011-10-25 06:44:01 +0000833 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000834 {
835 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000836 OptionGroupWriteMemory () :
837 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000838 {
Chris Lattner24943d22010-06-08 16:52:24 +0000839 }
840
841 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000842 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000843 {
844 }
845
Greg Claytona42880a2011-10-25 06:44:01 +0000846 virtual uint32_t
847 GetNumDefinitions ()
848 {
849 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
850 }
851
852 virtual const OptionDefinition*
853 GetDefinitions ()
854 {
855 return g_memory_write_option_table;
856 }
857
Chris Lattner24943d22010-06-08 16:52:24 +0000858 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000859 SetOptionValue (CommandInterpreter &interpreter,
860 uint32_t option_idx,
861 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000862 {
863 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000864 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
865
Chris Lattner24943d22010-06-08 16:52:24 +0000866 switch (short_option)
867 {
Greg Claytona42880a2011-10-25 06:44:01 +0000868 case 'i':
869 m_infile.SetFile (option_arg, true);
870 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000871 {
Greg Claytona42880a2011-10-25 06:44:01 +0000872 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000873 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000874 }
Greg Claytona42880a2011-10-25 06:44:01 +0000875 break;
876
877 case 'o':
878 {
879 bool success;
880 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
881 if (!success)
882 {
Greg Clayton9c236732011-10-26 00:56:27 +0000883 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000884 }
885 }
886 break;
887
888 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000889 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000890 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000891 }
892 return error;
893 }
Greg Claytona42880a2011-10-25 06:44:01 +0000894
895 virtual void
896 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000897 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000898 m_infile.Clear();
899 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000900 }
901
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000902 FileSpec m_infile;
903 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000904 };
905
Greg Clayton238c0a12010-09-18 01:14:36 +0000906 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000907 CommandObjectParsed (interpreter,
908 "memory write",
909 "Write to the memory of the process being debugged.",
910 NULL,
911 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000912 m_option_group (interpreter),
913 m_format_options (eFormatBytes, 1, UINT64_MAX),
914 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000915 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000916 CommandArgumentEntry arg1;
917 CommandArgumentEntry arg2;
918 CommandArgumentData addr_arg;
919 CommandArgumentData value_arg;
920
921 // Define the first (and only) variant of this arg.
922 addr_arg.arg_type = eArgTypeAddress;
923 addr_arg.arg_repetition = eArgRepeatPlain;
924
925 // There is only one variant this argument could be; put it into the argument entry.
926 arg1.push_back (addr_arg);
927
928 // Define the first (and only) variant of this arg.
929 value_arg.arg_type = eArgTypeValue;
930 value_arg.arg_repetition = eArgRepeatPlus;
931
932 // There is only one variant this argument could be; put it into the argument entry.
933 arg2.push_back (value_arg);
934
935 // Push the data for the first argument into the m_arguments vector.
936 m_arguments.push_back (arg1);
937 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000938
939 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
940 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
941 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
942 m_option_group.Finalize();
943
Chris Lattner24943d22010-06-08 16:52:24 +0000944 }
945
946 virtual
947 ~CommandObjectMemoryWrite ()
948 {
949 }
950
951 Options *
952 GetOptions ()
953 {
Greg Claytona42880a2011-10-25 06:44:01 +0000954 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000955 }
956
957 bool
958 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
959 {
960 if (total_byte_size > 8)
961 return false;
962
963 if (total_byte_size == 8)
964 return true;
965
966 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
967 return uval64 <= max;
968 }
969
970 bool
971 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
972 {
973 if (total_byte_size > 8)
974 return false;
975
976 if (total_byte_size == 8)
977 return true;
978
979 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
980 const int64_t min = ~(max);
981 return min <= sval64 && sval64 <= max;
982 }
983
Jim Inghamda26bd22012-06-08 21:56:10 +0000984protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000985 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000986 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000987 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000988 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000989 if (process == NULL)
990 {
991 result.AppendError("need a process to read memory");
992 result.SetStatus(eReturnStatusFailed);
993 return false;
994 }
995
996 const size_t argc = command.GetArgumentCount();
997
Greg Claytona42880a2011-10-25 06:44:01 +0000998 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000999 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001000 if (argc < 1)
1001 {
1002 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1003 result.SetStatus(eReturnStatusFailed);
1004 return false;
1005 }
1006 }
1007 else if (argc < 2)
1008 {
1009 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 +00001010 result.SetStatus(eReturnStatusFailed);
1011 return false;
1012 }
1013
Chris Lattner24943d22010-06-08 16:52:24 +00001014 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +00001015 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1016 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +00001017
Greg Claytona42880a2011-10-25 06:44:01 +00001018 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1019 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +00001020
Chris Lattner24943d22010-06-08 16:52:24 +00001021 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
1022
1023 if (addr == LLDB_INVALID_ADDRESS)
1024 {
1025 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
1026 result.SetStatus(eReturnStatusFailed);
1027 return false;
1028 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001029
Greg Claytona42880a2011-10-25 06:44:01 +00001030 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001031 {
1032 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +00001033 if (item_byte_size > 0)
1034 length = item_byte_size;
1035 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001036 if (data_sp)
1037 {
1038 length = data_sp->GetByteSize();
1039 if (length > 0)
1040 {
1041 Error error;
1042 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1043
1044 if (bytes_written == length)
1045 {
1046 // All bytes written
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001047 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001048 result.SetStatus(eReturnStatusSuccessFinishResult);
1049 }
1050 else if (bytes_written > 0)
1051 {
1052 // Some byte written
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001053 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001054 result.SetStatus(eReturnStatusSuccessFinishResult);
1055 }
1056 else
1057 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001058 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001059 result.SetStatus(eReturnStatusFailed);
1060 }
1061 }
1062 }
1063 else
1064 {
1065 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1066 result.SetStatus(eReturnStatusFailed);
1067 }
1068 return result.Succeeded();
1069 }
Greg Claytona42880a2011-10-25 06:44:01 +00001070 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001071 {
Greg Claytona42880a2011-10-25 06:44:01 +00001072 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001073 item_byte_size = buffer.GetAddressByteSize();
1074 else
1075 item_byte_size = 1;
1076 }
1077
Chris Lattner24943d22010-06-08 16:52:24 +00001078 command.Shift(); // shift off the address argument
1079 uint64_t uval64;
1080 int64_t sval64;
1081 bool success = false;
1082 const uint32_t num_value_args = command.GetArgumentCount();
1083 uint32_t i;
1084 for (i=0; i<num_value_args; ++i)
1085 {
1086 const char *value_str = command.GetArgumentAtIndex(i);
1087
Greg Claytona42880a2011-10-25 06:44:01 +00001088 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001089 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001090 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001091 case eFormatFloat: // TODO: add support for floats soon
1092 case eFormatCharPrintable:
1093 case eFormatBytesWithASCII:
1094 case eFormatComplex:
1095 case eFormatEnum:
1096 case eFormatUnicode16:
1097 case eFormatUnicode32:
1098 case eFormatVectorOfChar:
1099 case eFormatVectorOfSInt8:
1100 case eFormatVectorOfUInt8:
1101 case eFormatVectorOfSInt16:
1102 case eFormatVectorOfUInt16:
1103 case eFormatVectorOfSInt32:
1104 case eFormatVectorOfUInt32:
1105 case eFormatVectorOfSInt64:
1106 case eFormatVectorOfUInt64:
1107 case eFormatVectorOfFloat32:
1108 case eFormatVectorOfFloat64:
1109 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001110 case eFormatOSType:
1111 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001112 case eFormatAddressInfo:
1113 case eFormatHexFloat:
1114 case eFormatInstruction:
Sean Callanan96abc622012-08-08 17:35:10 +00001115 case eFormatVoid:
Chris Lattner24943d22010-06-08 16:52:24 +00001116 result.AppendError("unsupported format for writing memory");
1117 result.SetStatus(eReturnStatusFailed);
1118 return false;
1119
1120 case eFormatDefault:
1121 case eFormatBytes:
1122 case eFormatHex:
Enrico Granata535543d2012-08-09 19:33:34 +00001123 case eFormatHexUppercase:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001124 case eFormatPointer:
1125
Chris Lattner24943d22010-06-08 16:52:24 +00001126 // Decode hex bytes
1127 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1128 if (!success)
1129 {
1130 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1131 result.SetStatus(eReturnStatusFailed);
1132 return false;
1133 }
1134 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1135 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001136 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001137 result.SetStatus(eReturnStatusFailed);
1138 return false;
1139 }
1140 buffer.PutMaxHex64 (uval64, item_byte_size);
1141 break;
1142
1143 case eFormatBoolean:
1144 uval64 = Args::StringToBoolean(value_str, false, &success);
1145 if (!success)
1146 {
1147 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1148 result.SetStatus(eReturnStatusFailed);
1149 return false;
1150 }
1151 buffer.PutMaxHex64 (uval64, item_byte_size);
1152 break;
1153
1154 case eFormatBinary:
1155 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1156 if (!success)
1157 {
1158 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1159 result.SetStatus(eReturnStatusFailed);
1160 return false;
1161 }
1162 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1163 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001164 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001165 result.SetStatus(eReturnStatusFailed);
1166 return false;
1167 }
1168 buffer.PutMaxHex64 (uval64, item_byte_size);
1169 break;
1170
Greg Clayton307fa072011-06-17 23:50:44 +00001171 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001172 case eFormatChar:
1173 case eFormatCString:
1174 if (value_str[0])
1175 {
1176 size_t len = strlen (value_str);
1177 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001178 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001179 ++len;
1180 Error error;
1181 if (process->WriteMemory (addr, value_str, len, error) == len)
1182 {
1183 addr += len;
1184 }
1185 else
1186 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001187 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +00001188 result.SetStatus(eReturnStatusFailed);
1189 return false;
1190 }
1191 }
1192 break;
1193
1194 case eFormatDecimal:
1195 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1196 if (!success)
1197 {
1198 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1199 result.SetStatus(eReturnStatusFailed);
1200 return false;
1201 }
1202 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1203 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001204 result.AppendErrorWithFormat ("Value %" PRIi64 " 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 +00001205 result.SetStatus(eReturnStatusFailed);
1206 return false;
1207 }
1208 buffer.PutMaxHex64 (sval64, item_byte_size);
1209 break;
1210
1211 case eFormatUnsigned:
1212 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1213 if (!success)
1214 {
1215 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1216 result.SetStatus(eReturnStatusFailed);
1217 return false;
1218 }
1219 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1220 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001221 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001222 result.SetStatus(eReturnStatusFailed);
1223 return false;
1224 }
1225 buffer.PutMaxHex64 (uval64, item_byte_size);
1226 break;
1227
1228 case eFormatOctal:
1229 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1230 if (!success)
1231 {
1232 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1233 result.SetStatus(eReturnStatusFailed);
1234 return false;
1235 }
1236 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1237 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001238 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001239 result.SetStatus(eReturnStatusFailed);
1240 return false;
1241 }
1242 buffer.PutMaxHex64 (uval64, item_byte_size);
1243 break;
1244 }
1245 }
1246
1247 if (!buffer.GetString().empty())
1248 {
1249 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001250 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001251 return true;
1252 else
1253 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001254 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +00001255 result.SetStatus(eReturnStatusFailed);
1256 return false;
1257 }
1258 }
1259 return true;
1260 }
1261
Greg Claytona42880a2011-10-25 06:44:01 +00001262 OptionGroupOptions m_option_group;
1263 OptionGroupFormat m_format_options;
1264 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001265};
1266
Chris Lattner24943d22010-06-08 16:52:24 +00001267
1268//-------------------------------------------------------------------------
1269// CommandObjectMemory
1270//-------------------------------------------------------------------------
1271
Greg Clayton63094e02010-06-23 01:19:29 +00001272CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001273 CommandObjectMultiword (interpreter,
1274 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001275 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001276 "memory <subcommand> [<subcommand-options>]")
1277{
Greg Clayton238c0a12010-09-18 01:14:36 +00001278 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1279 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001280}
1281
1282CommandObjectMemory::~CommandObjectMemory ()
1283{
1284}