blob: c312816d539234d93cfe192669101386d319adcf [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"
Sean Callanan3e80cd92011-10-12 02:08:07 +000028#include "lldb/Symbol/ClangNamespaceDecl.h"
Chris Lattner24943d22010-06-08 16:52:24 +000029#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000030#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000031
32using namespace lldb;
33using namespace lldb_private;
34
Greg Clayton56bbdaf2011-04-28 20:55:26 +000035static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000036g_option_table[] =
37{
Greg Clayton57b3c6b2011-04-27 22:04:39 +000038 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
39 { 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 +000040 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
41 { 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 +000042};
43
44
45
46class OptionGroupReadMemory : public OptionGroup
47{
48public:
49
50 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000051 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000052 m_output_as_binary (false),
53 m_view_as_type()
54 {
55 }
56
57 virtual
58 ~OptionGroupReadMemory ()
59 {
60 }
61
62
63 virtual uint32_t
64 GetNumDefinitions ()
65 {
66 return sizeof (g_option_table) / sizeof (OptionDefinition);
67 }
68
69 virtual const OptionDefinition*
70 GetDefinitions ()
71 {
72 return g_option_table;
73 }
74
75 virtual Error
76 SetOptionValue (CommandInterpreter &interpreter,
77 uint32_t option_idx,
78 const char *option_arg)
79 {
80 Error error;
81 char short_option = (char) g_option_table[option_idx].short_option;
82
83 switch (short_option)
84 {
85 case 'l':
86 error = m_num_per_line.SetValueFromCString (option_arg);
87 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000088 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000089 break;
Greg Claytona42880a2011-10-25 06:44:01 +000090
Greg Clayton57b3c6b2011-04-27 22:04:39 +000091 case 'b':
92 m_output_as_binary = true;
93 break;
94
95 case 't':
96 error = m_view_as_type.SetValueFromCString (option_arg);
97 break;
Sean Callanan8a6f3e92012-04-28 01:27:38 +000098
99 case 'r':
100 m_force = true;
101 break;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000102
103 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000104 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000105 break;
106 }
107 return error;
108 }
109
110 virtual void
111 OptionParsingStarting (CommandInterpreter &interpreter)
112 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000113 m_num_per_line.Clear();
114 m_output_as_binary = false;
115 m_view_as_type.Clear();
116 }
117
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000118 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000119 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000120 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000121 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000122 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
123 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000124 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000125 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000126 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000127
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000128 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000129 {
130 default:
131 break;
132
133 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000134 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000135 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000136 if (!num_per_line_option_set)
137 m_num_per_line = 1;
138 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000139 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000140 break;
141
142 case eFormatCString:
143 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000144
145 case eFormatInstruction:
146 if (count_option_set)
147 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue();
148 m_num_per_line = 1;
149 break;
150
151 case eFormatAddressInfo:
152 if (!byte_size_option_set)
153 byte_size_value = target->GetArchitecture().GetAddressByteSize();
154 m_num_per_line = 1;
155 if (!count_option_set)
156 format_options.GetCountValue() = 8;
157 break;
158
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000159 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000160 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000161 if (!num_per_line_option_set)
162 m_num_per_line = 4;
163 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000164 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000165 break;
166
167 case eFormatBinary:
168 case eFormatFloat:
169 case eFormatOctal:
170 case eFormatDecimal:
171 case eFormatEnum:
172 case eFormatUnicode16:
173 case eFormatUnicode32:
174 case eFormatUnsigned:
Greg Clayton24a6bd92011-10-27 17:55:14 +0000175 case eFormatHexFloat:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000176 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000177 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000178 if (!num_per_line_option_set)
179 m_num_per_line = 1;
180 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000181 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000182 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000183
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000184 case eFormatBytes:
185 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000186 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000187 {
Greg Claytona42880a2011-10-25 06:44:01 +0000188 if (byte_size_value > 1)
Johnny Chenbf9ba592012-03-06 01:17:59 +0000189 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n"
190 "\tconsider using a different display format or don't specify the byte size",
191 byte_size_value.GetCurrentValue());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000192 }
193 else
Greg Claytona42880a2011-10-25 06:44:01 +0000194 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000195 if (!num_per_line_option_set)
196 m_num_per_line = 16;
197 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000198 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000199 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000200 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000201 case eFormatChar:
202 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000203 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000204 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000205 if (!num_per_line_option_set)
206 m_num_per_line = 32;
207 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000208 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000209 break;
210 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000211 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000212 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000213 if (!num_per_line_option_set)
214 m_num_per_line = 1;
215 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000216 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000217 break;
218 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000219 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000220 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000221 if (!num_per_line_option_set)
222 {
Greg Claytona42880a2011-10-25 06:44:01 +0000223 switch (byte_size_value)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000224 {
225 case 1:
226 case 2:
227 m_num_per_line = 8;
228 break;
229 case 4:
230 m_num_per_line = 4;
231 break;
232 case 8:
233 m_num_per_line = 2;
234 break;
235 default:
236 m_num_per_line = 1;
237 break;
238 }
239 }
240 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000241 count_value = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000242 break;
243
244 case eFormatVectorOfChar:
245 case eFormatVectorOfSInt8:
246 case eFormatVectorOfUInt8:
247 case eFormatVectorOfSInt16:
248 case eFormatVectorOfUInt16:
249 case eFormatVectorOfSInt32:
250 case eFormatVectorOfUInt32:
251 case eFormatVectorOfSInt64:
252 case eFormatVectorOfUInt64:
253 case eFormatVectorOfFloat32:
254 case eFormatVectorOfFloat64:
255 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000256 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000257 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000258 if (!num_per_line_option_set)
259 m_num_per_line = 1;
260 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000261 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000262 break;
263 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000264 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000265 }
266
Greg Clayton902b5be2011-10-26 04:32:38 +0000267 bool
268 AnyOptionWasSet () const
269 {
270 return m_num_per_line.OptionWasSet() ||
271 m_output_as_binary ||
272 m_view_as_type.OptionWasSet();
273 }
274
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000275 OptionValueUInt64 m_num_per_line;
276 bool m_output_as_binary;
277 OptionValueString m_view_as_type;
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000278 bool m_force;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000279};
280
281
282
Chris Lattner24943d22010-06-08 16:52:24 +0000283//----------------------------------------------------------------------
284// Read memory from the inferior process
285//----------------------------------------------------------------------
286class CommandObjectMemoryRead : public CommandObject
287{
288public:
289
Greg Clayton238c0a12010-09-18 01:14:36 +0000290 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
291 CommandObject (interpreter,
292 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000293 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000294 NULL,
Jim Ingham8cc3f692011-07-09 00:55:34 +0000295 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000296 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000297 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000298 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000299 m_outfile_options (),
Greg Clayton902b5be2011-10-26 04:32:38 +0000300 m_varobj_options(),
301 m_next_addr(LLDB_INVALID_ADDRESS),
302 m_prev_byte_size(0),
303 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
304 m_prev_memory_options (),
305 m_prev_outfile_options (),
306 m_prev_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000307 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000308 CommandArgumentEntry arg1;
309 CommandArgumentEntry arg2;
310 CommandArgumentData start_addr_arg;
311 CommandArgumentData end_addr_arg;
312
313 // Define the first (and only) variant of this arg.
314 start_addr_arg.arg_type = eArgTypeStartAddress;
315 start_addr_arg.arg_repetition = eArgRepeatPlain;
316
317 // There is only one variant this argument could be; put it into the argument entry.
318 arg1.push_back (start_addr_arg);
319
320 // Define the first (and only) variant of this arg.
321 end_addr_arg.arg_type = eArgTypeEndAddress;
322 end_addr_arg.arg_repetition = eArgRepeatOptional;
323
324 // There is only one variant this argument could be; put it into the argument entry.
325 arg2.push_back (end_addr_arg);
326
327 // Push the data for the first argument into the m_arguments vector.
328 m_arguments.push_back (arg1);
329 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000330
Greg Claytona42880a2011-10-25 06:44:01 +0000331 // Add the "--format" and "--count" options to group 1 and 3
332 m_option_group.Append (&m_format_options,
333 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000334 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000335 m_option_group.Append (&m_format_options,
336 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000337 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Claytona42880a2011-10-25 06:44:01 +0000338 // Add the "--size" option to group 1 and 2
339 m_option_group.Append (&m_format_options,
340 OptionGroupFormat::OPTION_GROUP_SIZE,
341 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000342 m_option_group.Append (&m_memory_options);
343 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 +0000344 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000345 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000346 }
347
348 virtual
349 ~CommandObjectMemoryRead ()
350 {
351 }
352
353 Options *
354 GetOptions ()
355 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000356 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000357 }
358
Greg Clayton902b5be2011-10-26 04:32:38 +0000359 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
360 {
361 return m_cmd_name.c_str();
362 }
363
Chris Lattner24943d22010-06-08 16:52:24 +0000364 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000365 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000366 CommandReturnObject &result)
367 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000368 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000369 Target *target = exe_ctx.GetTargetPtr();
370 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000371 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000372 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000373 result.SetStatus(eReturnStatusFailed);
374 return false;
375 }
376 const size_t argc = command.GetArgumentCount();
377
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000378
Greg Clayton902b5be2011-10-26 04:32:38 +0000379 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000380 {
381 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
382 result.SetStatus(eReturnStatusFailed);
383 return false;
384 }
385
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000386 ClangASTType clang_ast_type;
387 Error error;
388
389 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000390 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
391 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000392 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000393 // We are viewing memory as a type
394 SymbolContext sc;
Greg Claytondc0a38c2012-03-26 23:03:23 +0000395 const bool exact_match = false;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000396 TypeList type_list;
397 uint32_t reference_count = 0;
398 uint32_t pointer_count = 0;
399 size_t idx;
400 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
401 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
402 std::string type_str(view_as_type_cstr);
403
404 // Remove all instances of g_keywords that are followed by spaces
405 for (size_t i = 0; i < g_num_keywords; ++i)
406 {
407 const char *keyword = g_keywords[i];
408 int keyword_len = ::strlen (keyword);
409 while ((idx = type_str.find (keyword)) != std::string::npos)
410 {
411 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
412 type_str.erase(idx, keyword_len+1);
413 }
414 }
415 bool done = type_str.empty();
416 //
417 idx = type_str.find_first_not_of (" \t");
418 if (idx > 0 && idx != std::string::npos)
419 type_str.erase (0, idx);
420 while (!done)
421 {
422 // Strip trailing spaces
423 if (type_str.empty())
424 done = true;
425 else
426 {
427 switch (type_str[type_str.size()-1])
428 {
429 case '*':
430 ++pointer_count;
431 // fall through...
432 case ' ':
433 case '\t':
434 type_str.erase(type_str.size()-1);
435 break;
436
437 case '&':
438 if (reference_count == 0)
439 {
440 reference_count = 1;
441 type_str.erase(type_str.size()-1);
442 }
443 else
444 {
445 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
446 result.SetStatus(eReturnStatusFailed);
447 return false;
448 }
449 break;
450
451 default:
452 done = true;
453 break;
454 }
455 }
456 }
457
458 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000459 StackFrame *frame = exe_ctx.GetFramePtr();
460 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000461 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000462 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000463 if (sc.module_sp)
464 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000465 sc.module_sp->FindTypes (sc,
466 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000467 exact_match,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000468 1,
469 type_list);
470 }
471 }
472 if (type_list.GetSize() == 0)
473 {
Greg Clayton9f95fb62012-04-06 17:41:13 +0000474 target->GetImages().FindTypes (sc,
Greg Clayton567e7f32011-09-22 04:58:26 +0000475 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000476 exact_match,
Greg Clayton567e7f32011-09-22 04:58:26 +0000477 1,
478 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000479 }
480
481 if (type_list.GetSize() == 0)
482 {
483 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
484 lookup_type_name.GetCString(),
485 view_as_type_cstr);
486 result.SetStatus(eReturnStatusFailed);
487 return false;
488 }
489
490 TypeSP type_sp (type_list.GetTypeAtIndex(0));
491 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
492
493 while (pointer_count > 0)
494 {
495 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
496 if (pointer_type)
497 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
498 else
499 {
500 result.AppendError ("unable make a pointer type\n");
501 result.SetStatus(eReturnStatusFailed);
502 return false;
503 }
504 --pointer_count;
505 }
506
Greg Claytona42880a2011-10-25 06:44:01 +0000507 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000508
Greg Claytona42880a2011-10-25 06:44:01 +0000509 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000510 {
511 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
512 view_as_type_cstr);
513 result.SetStatus(eReturnStatusFailed);
514 return false;
515 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000516
Greg Claytona42880a2011-10-25 06:44:01 +0000517 if (!m_format_options.GetCountValue().OptionWasSet())
518 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000519 }
520 else
521 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000522 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000523 }
524
525 // Look for invalid combinations of settings
526 if (error.Fail())
527 {
528 result.AppendErrorWithFormat("%s", error.AsCString());
529 result.SetStatus(eReturnStatusFailed);
530 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000531 }
532
Greg Clayton902b5be2011-10-26 04:32:38 +0000533 lldb::addr_t addr;
534 size_t total_byte_size = 0;
535 if (argc == 0)
536 {
537 // Use the last address and byte size and all options as they were
538 // if no options have been set
539 addr = m_next_addr;
540 total_byte_size = m_prev_byte_size;
541 if (!m_format_options.AnyOptionWasSet() &&
542 !m_memory_options.AnyOptionWasSet() &&
543 !m_outfile_options.AnyOptionWasSet() &&
544 !m_varobj_options.AnyOptionWasSet())
545 {
546 m_format_options = m_prev_format_options;
547 m_memory_options = m_prev_memory_options;
548 m_outfile_options = m_prev_outfile_options;
549 m_varobj_options = m_prev_varobj_options;
550 }
551 }
552
Greg Claytona42880a2011-10-25 06:44:01 +0000553 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
554 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000555 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000556
Chris Lattner24943d22010-06-08 16:52:24 +0000557 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000558 {
559 total_byte_size = item_count * item_byte_size;
560 if (total_byte_size == 0)
561 total_byte_size = 32;
562 }
Chris Lattner24943d22010-06-08 16:52:24 +0000563
Greg Clayton902b5be2011-10-26 04:32:38 +0000564 if (argc > 0)
565 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000566
567 if (addr == LLDB_INVALID_ADDRESS)
568 {
569 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
570 result.SetStatus(eReturnStatusFailed);
571 return false;
572 }
573
574 if (argc == 2)
575 {
576 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
577 if (end_addr == LLDB_INVALID_ADDRESS)
578 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000579 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000580 result.SetStatus(eReturnStatusFailed);
581 return false;
582 }
583 else if (end_addr <= addr)
584 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000585 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 +0000586 result.SetStatus(eReturnStatusFailed);
587 return false;
588 }
Greg Claytona42880a2011-10-25 06:44:01 +0000589 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000590 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000591 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 +0000592 result.SetStatus(eReturnStatusFailed);
593 return false;
594 }
595
596 total_byte_size = end_addr - addr;
597 item_count = total_byte_size / item_byte_size;
598 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000599
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000600 if (total_byte_size > 1024 && !m_memory_options.m_force)
601 {
602 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
603 result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
604 return false;
605 }
606
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000607 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000608 size_t bytes_read = 0;
609 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000610 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000611 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000612 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000613 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000614 if (bytes_read == 0)
615 {
616 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
617 result.AppendError(error.AsCString());
618 result.SetStatus(eReturnStatusFailed);
619 return false;
620 }
621
622 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000623 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 +0000624 else
625 {
626 m_next_addr = addr + bytes_read;
627 m_prev_byte_size = bytes_read;
628 m_prev_format_options = m_format_options;
629 m_prev_memory_options = m_memory_options;
630 m_prev_outfile_options = m_outfile_options;
631 m_prev_varobj_options = m_varobj_options;
632 }
Chris Lattner24943d22010-06-08 16:52:24 +0000633 }
634
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000635 StreamFile outfile_stream;
636 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000637 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
638 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000639 {
640 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000641 outfile_spec.GetPath (path, sizeof(path));
642
643 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
644 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
645 if (append)
646 open_options |= File::eOpenOptionAppend;
647
648 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000649 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000650 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000651 {
652 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
653 if (bytes_written > 0)
654 {
655 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
656 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000657 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000658 path);
659 return true;
660 }
661 else
662 {
663 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
664 result.SetStatus(eReturnStatusFailed);
665 return false;
666 }
667 }
668 else
669 {
670 // We are going to write ASCII to the file just point the
671 // output_stream to our outfile_stream...
672 output_stream = &outfile_stream;
673 }
674 }
675 else
676 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000677 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000678 result.SetStatus(eReturnStatusFailed);
679 return false;
680 }
681 }
682 else
683 {
684 output_stream = &result.GetOutputStream();
685 }
686
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000687
Greg Clayton24a6bd92011-10-27 17:55:14 +0000688 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000689 if (clang_ast_type.GetOpaqueQualType())
690 {
691 for (uint32_t i = 0; i<item_count; ++i)
692 {
693 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000694 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000695 StreamString name_strm;
696 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000697 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000698 name_strm.GetString().c_str(),
699 address,
700 clang_ast_type));
701 if (valobj_sp)
702 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000703 if (format != eFormatDefault)
704 valobj_sp->SetFormat (format);
705
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000706 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000707
Enrico Granata3069c622012-03-01 04:24:26 +0000708 ValueObject::DumpValueObjectOptions options;
709 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
710 .SetMaximumDepth(m_varobj_options.max_depth)
711 .SetShowLocation(m_varobj_options.show_location)
712 .SetShowTypes(m_varobj_options.show_types)
713 .SetUseObjectiveC(m_varobj_options.use_objc)
714 .SetScopeChecked(scope_already_checked)
715 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000716 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000717 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
718 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
719 .SetFormat(format)
720 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000721 ValueObject::DumpValueObject (*output_stream,
722 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000723 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000724 }
725 else
726 {
727 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
728 view_as_type_cstr,
729 name_strm.GetString().c_str());
730 result.SetStatus(eReturnStatusFailed);
731 return false;
732 }
733 }
734 return true;
735 }
736
737 result.SetStatus(eReturnStatusSuccessFinishResult);
738 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000739 target->GetArchitecture().GetByteOrder(),
740 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000741
742
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000743 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000744 uint32_t bytes_dumped = data.Dump (output_stream,
745 0,
746 m_format_options.GetFormat(),
747 item_byte_size,
748 item_count,
749 num_per_line,
750 addr,
751 0,
752 0,
753 exe_scope);
754 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000755 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000756 return true;
757 }
758
759protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000760 OptionGroupOptions m_option_group;
761 OptionGroupFormat m_format_options;
762 OptionGroupReadMemory m_memory_options;
763 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000764 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000765 lldb::addr_t m_next_addr;
766 lldb::addr_t m_prev_byte_size;
767 OptionGroupFormat m_prev_format_options;
768 OptionGroupReadMemory m_prev_memory_options;
769 OptionGroupOutputFile m_prev_outfile_options;
770 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000771};
772
Greg Claytona42880a2011-10-25 06:44:01 +0000773
774OptionDefinition
775g_memory_write_option_table[] =
776{
777{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
778{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
779};
780
781
Chris Lattner24943d22010-06-08 16:52:24 +0000782//----------------------------------------------------------------------
783// Write memory to the inferior process
784//----------------------------------------------------------------------
785class CommandObjectMemoryWrite : public CommandObject
786{
787public:
788
Greg Claytona42880a2011-10-25 06:44:01 +0000789 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000790 {
791 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000792 OptionGroupWriteMemory () :
793 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000794 {
Chris Lattner24943d22010-06-08 16:52:24 +0000795 }
796
797 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000798 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000799 {
800 }
801
Greg Claytona42880a2011-10-25 06:44:01 +0000802 virtual uint32_t
803 GetNumDefinitions ()
804 {
805 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
806 }
807
808 virtual const OptionDefinition*
809 GetDefinitions ()
810 {
811 return g_memory_write_option_table;
812 }
813
Chris Lattner24943d22010-06-08 16:52:24 +0000814 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000815 SetOptionValue (CommandInterpreter &interpreter,
816 uint32_t option_idx,
817 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000818 {
819 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000820 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
821
Chris Lattner24943d22010-06-08 16:52:24 +0000822 switch (short_option)
823 {
Greg Claytona42880a2011-10-25 06:44:01 +0000824 case 'i':
825 m_infile.SetFile (option_arg, true);
826 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000827 {
Greg Claytona42880a2011-10-25 06:44:01 +0000828 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000829 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000830 }
Greg Claytona42880a2011-10-25 06:44:01 +0000831 break;
832
833 case 'o':
834 {
835 bool success;
836 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
837 if (!success)
838 {
Greg Clayton9c236732011-10-26 00:56:27 +0000839 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000840 }
841 }
842 break;
843
844 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000845 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000846 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000847 }
848 return error;
849 }
Greg Claytona42880a2011-10-25 06:44:01 +0000850
851 virtual void
852 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000853 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000854 m_infile.Clear();
855 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000856 }
857
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000858 FileSpec m_infile;
859 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000860 };
861
Greg Clayton238c0a12010-09-18 01:14:36 +0000862 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
863 CommandObject (interpreter,
864 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000865 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000866 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
867 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000868 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000869 m_option_group (interpreter),
870 m_format_options (eFormatBytes, 1, UINT64_MAX),
871 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000872 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000873 CommandArgumentEntry arg1;
874 CommandArgumentEntry arg2;
875 CommandArgumentData addr_arg;
876 CommandArgumentData value_arg;
877
878 // Define the first (and only) variant of this arg.
879 addr_arg.arg_type = eArgTypeAddress;
880 addr_arg.arg_repetition = eArgRepeatPlain;
881
882 // There is only one variant this argument could be; put it into the argument entry.
883 arg1.push_back (addr_arg);
884
885 // Define the first (and only) variant of this arg.
886 value_arg.arg_type = eArgTypeValue;
887 value_arg.arg_repetition = eArgRepeatPlus;
888
889 // There is only one variant this argument could be; put it into the argument entry.
890 arg2.push_back (value_arg);
891
892 // Push the data for the first argument into the m_arguments vector.
893 m_arguments.push_back (arg1);
894 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000895
896 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
897 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
898 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
899 m_option_group.Finalize();
900
Chris Lattner24943d22010-06-08 16:52:24 +0000901 }
902
903 virtual
904 ~CommandObjectMemoryWrite ()
905 {
906 }
907
908 Options *
909 GetOptions ()
910 {
Greg Claytona42880a2011-10-25 06:44:01 +0000911 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000912 }
913
914 bool
915 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
916 {
917 if (total_byte_size > 8)
918 return false;
919
920 if (total_byte_size == 8)
921 return true;
922
923 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
924 return uval64 <= max;
925 }
926
927 bool
928 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
929 {
930 if (total_byte_size > 8)
931 return false;
932
933 if (total_byte_size == 8)
934 return true;
935
936 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
937 const int64_t min = ~(max);
938 return min <= sval64 && sval64 <= max;
939 }
940
941 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000942 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000943 CommandReturnObject &result)
944 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000945 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000946 if (process == NULL)
947 {
948 result.AppendError("need a process to read memory");
949 result.SetStatus(eReturnStatusFailed);
950 return false;
951 }
952
953 const size_t argc = command.GetArgumentCount();
954
Greg Claytona42880a2011-10-25 06:44:01 +0000955 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000956 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000957 if (argc < 1)
958 {
959 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
960 result.SetStatus(eReturnStatusFailed);
961 return false;
962 }
963 }
964 else if (argc < 2)
965 {
966 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 +0000967 result.SetStatus(eReturnStatusFailed);
968 return false;
969 }
970
Chris Lattner24943d22010-06-08 16:52:24 +0000971 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000972 process->GetTarget().GetArchitecture().GetAddressByteSize(),
973 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000974
Greg Claytona42880a2011-10-25 06:44:01 +0000975 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
976 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000977
Chris Lattner24943d22010-06-08 16:52:24 +0000978 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
979
980 if (addr == LLDB_INVALID_ADDRESS)
981 {
982 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
983 result.SetStatus(eReturnStatusFailed);
984 return false;
985 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000986
Greg Claytona42880a2011-10-25 06:44:01 +0000987 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000988 {
989 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000990 if (item_byte_size > 0)
991 length = item_byte_size;
992 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000993 if (data_sp)
994 {
995 length = data_sp->GetByteSize();
996 if (length > 0)
997 {
998 Error error;
999 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1000
1001 if (bytes_written == length)
1002 {
1003 // All bytes written
1004 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
1005 result.SetStatus(eReturnStatusSuccessFinishResult);
1006 }
1007 else if (bytes_written > 0)
1008 {
1009 // Some byte written
1010 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
1011 result.SetStatus(eReturnStatusSuccessFinishResult);
1012 }
1013 else
1014 {
1015 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1016 result.SetStatus(eReturnStatusFailed);
1017 }
1018 }
1019 }
1020 else
1021 {
1022 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1023 result.SetStatus(eReturnStatusFailed);
1024 }
1025 return result.Succeeded();
1026 }
Greg Claytona42880a2011-10-25 06:44:01 +00001027 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001028 {
Greg Claytona42880a2011-10-25 06:44:01 +00001029 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001030 item_byte_size = buffer.GetAddressByteSize();
1031 else
1032 item_byte_size = 1;
1033 }
1034
Chris Lattner24943d22010-06-08 16:52:24 +00001035 command.Shift(); // shift off the address argument
1036 uint64_t uval64;
1037 int64_t sval64;
1038 bool success = false;
1039 const uint32_t num_value_args = command.GetArgumentCount();
1040 uint32_t i;
1041 for (i=0; i<num_value_args; ++i)
1042 {
1043 const char *value_str = command.GetArgumentAtIndex(i);
1044
Greg Claytona42880a2011-10-25 06:44:01 +00001045 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001046 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001047 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001048 case eFormatFloat: // TODO: add support for floats soon
1049 case eFormatCharPrintable:
1050 case eFormatBytesWithASCII:
1051 case eFormatComplex:
1052 case eFormatEnum:
1053 case eFormatUnicode16:
1054 case eFormatUnicode32:
1055 case eFormatVectorOfChar:
1056 case eFormatVectorOfSInt8:
1057 case eFormatVectorOfUInt8:
1058 case eFormatVectorOfSInt16:
1059 case eFormatVectorOfUInt16:
1060 case eFormatVectorOfSInt32:
1061 case eFormatVectorOfUInt32:
1062 case eFormatVectorOfSInt64:
1063 case eFormatVectorOfUInt64:
1064 case eFormatVectorOfFloat32:
1065 case eFormatVectorOfFloat64:
1066 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001067 case eFormatOSType:
1068 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001069 case eFormatAddressInfo:
1070 case eFormatHexFloat:
1071 case eFormatInstruction:
Chris Lattner24943d22010-06-08 16:52:24 +00001072 result.AppendError("unsupported format for writing memory");
1073 result.SetStatus(eReturnStatusFailed);
1074 return false;
1075
1076 case eFormatDefault:
1077 case eFormatBytes:
1078 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001079 case eFormatPointer:
1080
Chris Lattner24943d22010-06-08 16:52:24 +00001081 // Decode hex bytes
1082 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1083 if (!success)
1084 {
1085 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1086 result.SetStatus(eReturnStatusFailed);
1087 return false;
1088 }
1089 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1090 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001091 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 +00001092 result.SetStatus(eReturnStatusFailed);
1093 return false;
1094 }
1095 buffer.PutMaxHex64 (uval64, item_byte_size);
1096 break;
1097
1098 case eFormatBoolean:
1099 uval64 = Args::StringToBoolean(value_str, false, &success);
1100 if (!success)
1101 {
1102 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1103 result.SetStatus(eReturnStatusFailed);
1104 return false;
1105 }
1106 buffer.PutMaxHex64 (uval64, item_byte_size);
1107 break;
1108
1109 case eFormatBinary:
1110 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1111 if (!success)
1112 {
1113 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1114 result.SetStatus(eReturnStatusFailed);
1115 return false;
1116 }
1117 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1118 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001119 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 +00001120 result.SetStatus(eReturnStatusFailed);
1121 return false;
1122 }
1123 buffer.PutMaxHex64 (uval64, item_byte_size);
1124 break;
1125
Greg Clayton307fa072011-06-17 23:50:44 +00001126 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001127 case eFormatChar:
1128 case eFormatCString:
1129 if (value_str[0])
1130 {
1131 size_t len = strlen (value_str);
1132 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001133 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001134 ++len;
1135 Error error;
1136 if (process->WriteMemory (addr, value_str, len, error) == len)
1137 {
1138 addr += len;
1139 }
1140 else
1141 {
1142 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1143 result.SetStatus(eReturnStatusFailed);
1144 return false;
1145 }
1146 }
1147 break;
1148
1149 case eFormatDecimal:
1150 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1151 if (!success)
1152 {
1153 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1154 result.SetStatus(eReturnStatusFailed);
1155 return false;
1156 }
1157 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1158 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001159 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 +00001160 result.SetStatus(eReturnStatusFailed);
1161 return false;
1162 }
1163 buffer.PutMaxHex64 (sval64, item_byte_size);
1164 break;
1165
1166 case eFormatUnsigned:
1167 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1168 if (!success)
1169 {
1170 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1171 result.SetStatus(eReturnStatusFailed);
1172 return false;
1173 }
1174 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1175 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001176 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 +00001177 result.SetStatus(eReturnStatusFailed);
1178 return false;
1179 }
1180 buffer.PutMaxHex64 (uval64, item_byte_size);
1181 break;
1182
1183 case eFormatOctal:
1184 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1185 if (!success)
1186 {
1187 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1188 result.SetStatus(eReturnStatusFailed);
1189 return false;
1190 }
1191 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1192 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001193 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 +00001194 result.SetStatus(eReturnStatusFailed);
1195 return false;
1196 }
1197 buffer.PutMaxHex64 (uval64, item_byte_size);
1198 break;
1199 }
1200 }
1201
1202 if (!buffer.GetString().empty())
1203 {
1204 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001205 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001206 return true;
1207 else
1208 {
1209 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1210 result.SetStatus(eReturnStatusFailed);
1211 return false;
1212 }
1213 }
1214 return true;
1215 }
1216
1217protected:
Greg Claytona42880a2011-10-25 06:44:01 +00001218
1219 OptionGroupOptions m_option_group;
1220 OptionGroupFormat m_format_options;
1221 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001222};
1223
Chris Lattner24943d22010-06-08 16:52:24 +00001224
1225//-------------------------------------------------------------------------
1226// CommandObjectMemory
1227//-------------------------------------------------------------------------
1228
Greg Clayton63094e02010-06-23 01:19:29 +00001229CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001230 CommandObjectMultiword (interpreter,
1231 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001232 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001233 "memory <subcommand> [<subcommand-options>]")
1234{
Greg Clayton238c0a12010-09-18 01:14:36 +00001235 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1236 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001237}
1238
1239CommandObjectMemory::~CommandObjectMemory ()
1240{
1241}