blob: 6b495ac15c06062dc22427a081918505ccd79144 [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 {
Greg Clayton04e6ada2012-05-25 17:05:55 +0000616 const char *error_cstr = error.AsCString();
617 if (error_cstr && error_cstr[0])
618 {
619 result.AppendError(error_cstr);
620 }
621 else
622 {
623 result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr);
624 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000625 result.SetStatus(eReturnStatusFailed);
626 return false;
627 }
628
629 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000630 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 +0000631 else
632 {
633 m_next_addr = addr + bytes_read;
634 m_prev_byte_size = bytes_read;
635 m_prev_format_options = m_format_options;
636 m_prev_memory_options = m_memory_options;
637 m_prev_outfile_options = m_outfile_options;
638 m_prev_varobj_options = m_varobj_options;
639 }
Chris Lattner24943d22010-06-08 16:52:24 +0000640 }
641
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000642 StreamFile outfile_stream;
643 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000644 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
645 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000646 {
647 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000648 outfile_spec.GetPath (path, sizeof(path));
649
650 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
651 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
652 if (append)
653 open_options |= File::eOpenOptionAppend;
654
655 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000656 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000657 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000658 {
659 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
660 if (bytes_written > 0)
661 {
662 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
663 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000664 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000665 path);
666 return true;
667 }
668 else
669 {
670 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
671 result.SetStatus(eReturnStatusFailed);
672 return false;
673 }
674 }
675 else
676 {
677 // We are going to write ASCII to the file just point the
678 // output_stream to our outfile_stream...
679 output_stream = &outfile_stream;
680 }
681 }
682 else
683 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000684 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000685 result.SetStatus(eReturnStatusFailed);
686 return false;
687 }
688 }
689 else
690 {
691 output_stream = &result.GetOutputStream();
692 }
693
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000694
Greg Clayton24a6bd92011-10-27 17:55:14 +0000695 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000696 if (clang_ast_type.GetOpaqueQualType())
697 {
698 for (uint32_t i = 0; i<item_count; ++i)
699 {
700 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000701 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000702 StreamString name_strm;
703 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000704 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000705 name_strm.GetString().c_str(),
706 address,
707 clang_ast_type));
708 if (valobj_sp)
709 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000710 if (format != eFormatDefault)
711 valobj_sp->SetFormat (format);
712
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000713 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000714
Enrico Granata3069c622012-03-01 04:24:26 +0000715 ValueObject::DumpValueObjectOptions options;
716 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
717 .SetMaximumDepth(m_varobj_options.max_depth)
718 .SetShowLocation(m_varobj_options.show_location)
719 .SetShowTypes(m_varobj_options.show_types)
720 .SetUseObjectiveC(m_varobj_options.use_objc)
721 .SetScopeChecked(scope_already_checked)
722 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000723 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000724 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
725 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
726 .SetFormat(format)
727 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000728 ValueObject::DumpValueObject (*output_stream,
729 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000730 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000731 }
732 else
733 {
734 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
735 view_as_type_cstr,
736 name_strm.GetString().c_str());
737 result.SetStatus(eReturnStatusFailed);
738 return false;
739 }
740 }
741 return true;
742 }
743
744 result.SetStatus(eReturnStatusSuccessFinishResult);
745 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000746 target->GetArchitecture().GetByteOrder(),
747 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000748
749
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000750 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000751 uint32_t bytes_dumped = data.Dump (output_stream,
752 0,
753 m_format_options.GetFormat(),
754 item_byte_size,
755 item_count,
756 num_per_line,
757 addr,
758 0,
759 0,
760 exe_scope);
761 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000762 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000763 return true;
764 }
765
766protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000767 OptionGroupOptions m_option_group;
768 OptionGroupFormat m_format_options;
769 OptionGroupReadMemory m_memory_options;
770 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000771 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000772 lldb::addr_t m_next_addr;
773 lldb::addr_t m_prev_byte_size;
774 OptionGroupFormat m_prev_format_options;
775 OptionGroupReadMemory m_prev_memory_options;
776 OptionGroupOutputFile m_prev_outfile_options;
777 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000778};
779
Greg Claytona42880a2011-10-25 06:44:01 +0000780
781OptionDefinition
782g_memory_write_option_table[] =
783{
784{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
785{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
786};
787
788
Chris Lattner24943d22010-06-08 16:52:24 +0000789//----------------------------------------------------------------------
790// Write memory to the inferior process
791//----------------------------------------------------------------------
792class CommandObjectMemoryWrite : public CommandObject
793{
794public:
795
Greg Claytona42880a2011-10-25 06:44:01 +0000796 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000797 {
798 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000799 OptionGroupWriteMemory () :
800 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000801 {
Chris Lattner24943d22010-06-08 16:52:24 +0000802 }
803
804 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000805 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000806 {
807 }
808
Greg Claytona42880a2011-10-25 06:44:01 +0000809 virtual uint32_t
810 GetNumDefinitions ()
811 {
812 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
813 }
814
815 virtual const OptionDefinition*
816 GetDefinitions ()
817 {
818 return g_memory_write_option_table;
819 }
820
Chris Lattner24943d22010-06-08 16:52:24 +0000821 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000822 SetOptionValue (CommandInterpreter &interpreter,
823 uint32_t option_idx,
824 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000825 {
826 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000827 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
828
Chris Lattner24943d22010-06-08 16:52:24 +0000829 switch (short_option)
830 {
Greg Claytona42880a2011-10-25 06:44:01 +0000831 case 'i':
832 m_infile.SetFile (option_arg, true);
833 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000834 {
Greg Claytona42880a2011-10-25 06:44:01 +0000835 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000836 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000837 }
Greg Claytona42880a2011-10-25 06:44:01 +0000838 break;
839
840 case 'o':
841 {
842 bool success;
843 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
844 if (!success)
845 {
Greg Clayton9c236732011-10-26 00:56:27 +0000846 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000847 }
848 }
849 break;
850
851 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000852 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000853 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000854 }
855 return error;
856 }
Greg Claytona42880a2011-10-25 06:44:01 +0000857
858 virtual void
859 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000860 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000861 m_infile.Clear();
862 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000863 }
864
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000865 FileSpec m_infile;
866 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000867 };
868
Greg Clayton238c0a12010-09-18 01:14:36 +0000869 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
870 CommandObject (interpreter,
871 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000872 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000873 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
874 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000875 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000876 m_option_group (interpreter),
877 m_format_options (eFormatBytes, 1, UINT64_MAX),
878 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000879 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000880 CommandArgumentEntry arg1;
881 CommandArgumentEntry arg2;
882 CommandArgumentData addr_arg;
883 CommandArgumentData value_arg;
884
885 // Define the first (and only) variant of this arg.
886 addr_arg.arg_type = eArgTypeAddress;
887 addr_arg.arg_repetition = eArgRepeatPlain;
888
889 // There is only one variant this argument could be; put it into the argument entry.
890 arg1.push_back (addr_arg);
891
892 // Define the first (and only) variant of this arg.
893 value_arg.arg_type = eArgTypeValue;
894 value_arg.arg_repetition = eArgRepeatPlus;
895
896 // There is only one variant this argument could be; put it into the argument entry.
897 arg2.push_back (value_arg);
898
899 // Push the data for the first argument into the m_arguments vector.
900 m_arguments.push_back (arg1);
901 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000902
903 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
904 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
905 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
906 m_option_group.Finalize();
907
Chris Lattner24943d22010-06-08 16:52:24 +0000908 }
909
910 virtual
911 ~CommandObjectMemoryWrite ()
912 {
913 }
914
915 Options *
916 GetOptions ()
917 {
Greg Claytona42880a2011-10-25 06:44:01 +0000918 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000919 }
920
921 bool
922 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
923 {
924 if (total_byte_size > 8)
925 return false;
926
927 if (total_byte_size == 8)
928 return true;
929
930 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
931 return uval64 <= max;
932 }
933
934 bool
935 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
936 {
937 if (total_byte_size > 8)
938 return false;
939
940 if (total_byte_size == 8)
941 return true;
942
943 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
944 const int64_t min = ~(max);
945 return min <= sval64 && sval64 <= max;
946 }
947
948 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000949 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000950 CommandReturnObject &result)
951 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000952 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000953 if (process == NULL)
954 {
955 result.AppendError("need a process to read memory");
956 result.SetStatus(eReturnStatusFailed);
957 return false;
958 }
959
960 const size_t argc = command.GetArgumentCount();
961
Greg Claytona42880a2011-10-25 06:44:01 +0000962 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000963 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000964 if (argc < 1)
965 {
966 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
967 result.SetStatus(eReturnStatusFailed);
968 return false;
969 }
970 }
971 else if (argc < 2)
972 {
973 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 +0000974 result.SetStatus(eReturnStatusFailed);
975 return false;
976 }
977
Chris Lattner24943d22010-06-08 16:52:24 +0000978 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000979 process->GetTarget().GetArchitecture().GetAddressByteSize(),
980 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000981
Greg Claytona42880a2011-10-25 06:44:01 +0000982 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
983 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000984
Chris Lattner24943d22010-06-08 16:52:24 +0000985 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
986
987 if (addr == LLDB_INVALID_ADDRESS)
988 {
989 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
990 result.SetStatus(eReturnStatusFailed);
991 return false;
992 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000993
Greg Claytona42880a2011-10-25 06:44:01 +0000994 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000995 {
996 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000997 if (item_byte_size > 0)
998 length = item_byte_size;
999 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001000 if (data_sp)
1001 {
1002 length = data_sp->GetByteSize();
1003 if (length > 0)
1004 {
1005 Error error;
1006 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1007
1008 if (bytes_written == length)
1009 {
1010 // All bytes written
1011 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
1012 result.SetStatus(eReturnStatusSuccessFinishResult);
1013 }
1014 else if (bytes_written > 0)
1015 {
1016 // Some byte written
1017 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
1018 result.SetStatus(eReturnStatusSuccessFinishResult);
1019 }
1020 else
1021 {
1022 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1023 result.SetStatus(eReturnStatusFailed);
1024 }
1025 }
1026 }
1027 else
1028 {
1029 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1030 result.SetStatus(eReturnStatusFailed);
1031 }
1032 return result.Succeeded();
1033 }
Greg Claytona42880a2011-10-25 06:44:01 +00001034 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001035 {
Greg Claytona42880a2011-10-25 06:44:01 +00001036 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001037 item_byte_size = buffer.GetAddressByteSize();
1038 else
1039 item_byte_size = 1;
1040 }
1041
Chris Lattner24943d22010-06-08 16:52:24 +00001042 command.Shift(); // shift off the address argument
1043 uint64_t uval64;
1044 int64_t sval64;
1045 bool success = false;
1046 const uint32_t num_value_args = command.GetArgumentCount();
1047 uint32_t i;
1048 for (i=0; i<num_value_args; ++i)
1049 {
1050 const char *value_str = command.GetArgumentAtIndex(i);
1051
Greg Claytona42880a2011-10-25 06:44:01 +00001052 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001053 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001054 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001055 case eFormatFloat: // TODO: add support for floats soon
1056 case eFormatCharPrintable:
1057 case eFormatBytesWithASCII:
1058 case eFormatComplex:
1059 case eFormatEnum:
1060 case eFormatUnicode16:
1061 case eFormatUnicode32:
1062 case eFormatVectorOfChar:
1063 case eFormatVectorOfSInt8:
1064 case eFormatVectorOfUInt8:
1065 case eFormatVectorOfSInt16:
1066 case eFormatVectorOfUInt16:
1067 case eFormatVectorOfSInt32:
1068 case eFormatVectorOfUInt32:
1069 case eFormatVectorOfSInt64:
1070 case eFormatVectorOfUInt64:
1071 case eFormatVectorOfFloat32:
1072 case eFormatVectorOfFloat64:
1073 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001074 case eFormatOSType:
1075 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001076 case eFormatAddressInfo:
1077 case eFormatHexFloat:
1078 case eFormatInstruction:
Chris Lattner24943d22010-06-08 16:52:24 +00001079 result.AppendError("unsupported format for writing memory");
1080 result.SetStatus(eReturnStatusFailed);
1081 return false;
1082
1083 case eFormatDefault:
1084 case eFormatBytes:
1085 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001086 case eFormatPointer:
1087
Chris Lattner24943d22010-06-08 16:52:24 +00001088 // Decode hex bytes
1089 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1090 if (!success)
1091 {
1092 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1093 result.SetStatus(eReturnStatusFailed);
1094 return false;
1095 }
1096 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1097 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001098 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 +00001099 result.SetStatus(eReturnStatusFailed);
1100 return false;
1101 }
1102 buffer.PutMaxHex64 (uval64, item_byte_size);
1103 break;
1104
1105 case eFormatBoolean:
1106 uval64 = Args::StringToBoolean(value_str, false, &success);
1107 if (!success)
1108 {
1109 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1110 result.SetStatus(eReturnStatusFailed);
1111 return false;
1112 }
1113 buffer.PutMaxHex64 (uval64, item_byte_size);
1114 break;
1115
1116 case eFormatBinary:
1117 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1118 if (!success)
1119 {
1120 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1121 result.SetStatus(eReturnStatusFailed);
1122 return false;
1123 }
1124 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1125 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001126 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 +00001127 result.SetStatus(eReturnStatusFailed);
1128 return false;
1129 }
1130 buffer.PutMaxHex64 (uval64, item_byte_size);
1131 break;
1132
Greg Clayton307fa072011-06-17 23:50:44 +00001133 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001134 case eFormatChar:
1135 case eFormatCString:
1136 if (value_str[0])
1137 {
1138 size_t len = strlen (value_str);
1139 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001140 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001141 ++len;
1142 Error error;
1143 if (process->WriteMemory (addr, value_str, len, error) == len)
1144 {
1145 addr += len;
1146 }
1147 else
1148 {
1149 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1150 result.SetStatus(eReturnStatusFailed);
1151 return false;
1152 }
1153 }
1154 break;
1155
1156 case eFormatDecimal:
1157 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1158 if (!success)
1159 {
1160 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1161 result.SetStatus(eReturnStatusFailed);
1162 return false;
1163 }
1164 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1165 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001166 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 +00001167 result.SetStatus(eReturnStatusFailed);
1168 return false;
1169 }
1170 buffer.PutMaxHex64 (sval64, item_byte_size);
1171 break;
1172
1173 case eFormatUnsigned:
1174 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1175 if (!success)
1176 {
1177 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1178 result.SetStatus(eReturnStatusFailed);
1179 return false;
1180 }
1181 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1182 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001183 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 +00001184 result.SetStatus(eReturnStatusFailed);
1185 return false;
1186 }
1187 buffer.PutMaxHex64 (uval64, item_byte_size);
1188 break;
1189
1190 case eFormatOctal:
1191 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1192 if (!success)
1193 {
1194 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1195 result.SetStatus(eReturnStatusFailed);
1196 return false;
1197 }
1198 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1199 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001200 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 +00001201 result.SetStatus(eReturnStatusFailed);
1202 return false;
1203 }
1204 buffer.PutMaxHex64 (uval64, item_byte_size);
1205 break;
1206 }
1207 }
1208
1209 if (!buffer.GetString().empty())
1210 {
1211 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001212 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001213 return true;
1214 else
1215 {
1216 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1217 result.SetStatus(eReturnStatusFailed);
1218 return false;
1219 }
1220 }
1221 return true;
1222 }
1223
1224protected:
Greg Claytona42880a2011-10-25 06:44:01 +00001225
1226 OptionGroupOptions m_option_group;
1227 OptionGroupFormat m_format_options;
1228 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001229};
1230
Chris Lattner24943d22010-06-08 16:52:24 +00001231
1232//-------------------------------------------------------------------------
1233// CommandObjectMemory
1234//-------------------------------------------------------------------------
1235
Greg Clayton63094e02010-06-23 01:19:29 +00001236CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001237 CommandObjectMultiword (interpreter,
1238 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001239 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001240 "memory <subcommand> [<subcommand-options>]")
1241{
Greg Clayton238c0a12010-09-18 01:14:36 +00001242 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1243 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001244}
1245
1246CommandObjectMemory::~CommandObjectMemory ()
1247{
1248}