blob: 947fc27a3c07d50ad849d01a32ba16103fe5ccd5 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012#include "CommandObjectMemory.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000020#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000021#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000023#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton66111032010-06-23 01:19:29 +000024#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000026#include "lldb/Interpreter/CommandInterpreter.h"
27#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000028#include "lldb/Interpreter/OptionGroupFormat.h"
29#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000030#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000031#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton1f746072012-08-29 21:13:06 +000032#include "lldb/Symbol/TypeList.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033#include "lldb/Target/Process.h"
Greg Clayton84c39662011-04-27 22:04:39 +000034#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035
36using namespace lldb;
37using namespace lldb_private;
38
Greg Clayton68ebae62011-04-28 20:55:26 +000039static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000040g_option_table[] =
41{
Greg Clayton84c39662011-04-27 22:04:39 +000042 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
43 { 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 Callanan3d654b32012-09-24 22:25:51 +000044 { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton2346fcf2012-11-02 21:14:58 +000045 { LLDB_OPT_SET_1|
46 LLDB_OPT_SET_2|
47 LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over 1024 bytes of memory."},
Greg Clayton84c39662011-04-27 22:04:39 +000048};
49
50
51
52class OptionGroupReadMemory : public OptionGroup
53{
54public:
55
56 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000057 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000058 m_output_as_binary (false),
59 m_view_as_type()
60 {
61 }
62
63 virtual
64 ~OptionGroupReadMemory ()
65 {
66 }
67
68
69 virtual uint32_t
70 GetNumDefinitions ()
71 {
72 return sizeof (g_option_table) / sizeof (OptionDefinition);
73 }
74
75 virtual const OptionDefinition*
76 GetDefinitions ()
77 {
78 return g_option_table;
79 }
80
81 virtual Error
82 SetOptionValue (CommandInterpreter &interpreter,
83 uint32_t option_idx,
84 const char *option_arg)
85 {
86 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000087 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000088
89 switch (short_option)
90 {
91 case 'l':
92 error = m_num_per_line.SetValueFromCString (option_arg);
93 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +000094 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +000095 break;
Greg Clayton1deb7962011-10-25 06:44:01 +000096
Greg Clayton84c39662011-04-27 22:04:39 +000097 case 'b':
98 m_output_as_binary = true;
99 break;
100
101 case 't':
102 error = m_view_as_type.SetValueFromCString (option_arg);
103 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000104
105 case 'r':
106 m_force = true;
107 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000108
109 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000110 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000111 break;
112 }
113 return error;
114 }
115
116 virtual void
117 OptionParsingStarting (CommandInterpreter &interpreter)
118 {
Greg Clayton84c39662011-04-27 22:04:39 +0000119 m_num_per_line.Clear();
120 m_output_as_binary = false;
121 m_view_as_type.Clear();
122 }
123
Greg Clayton68ebae62011-04-28 20:55:26 +0000124 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000125 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000126 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000127 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000128 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
129 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000130 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000131 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000132 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000133
Greg Clayton68ebae62011-04-28 20:55:26 +0000134 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000135 {
136 default:
137 break;
138
139 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000140 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000141 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000142 if (!num_per_line_option_set)
143 m_num_per_line = 1;
144 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000145 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000146 break;
147
148 case eFormatCString:
149 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000150
151 case eFormatInstruction:
152 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000153 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000154 m_num_per_line = 1;
155 break;
156
157 case eFormatAddressInfo:
158 if (!byte_size_option_set)
159 byte_size_value = target->GetArchitecture().GetAddressByteSize();
160 m_num_per_line = 1;
161 if (!count_option_set)
162 format_options.GetCountValue() = 8;
163 break;
164
Greg Clayton84c39662011-04-27 22:04:39 +0000165 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000166 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000167 if (!num_per_line_option_set)
168 m_num_per_line = 4;
169 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000170 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000171 break;
172
173 case eFormatBinary:
174 case eFormatFloat:
175 case eFormatOctal:
176 case eFormatDecimal:
177 case eFormatEnum:
178 case eFormatUnicode16:
179 case eFormatUnicode32:
180 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000181 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000182 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000183 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000184 if (!num_per_line_option_set)
185 m_num_per_line = 1;
186 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000187 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000188 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000189
Greg Clayton84c39662011-04-27 22:04:39 +0000190 case eFormatBytes:
191 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000192 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000193 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000194 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000195 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000196 "\tconsider using a different display format or don't specify the byte size",
197 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000198 }
199 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000200 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000201 if (!num_per_line_option_set)
202 m_num_per_line = 16;
203 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000204 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000205 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000206 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000207 case eFormatChar:
208 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000209 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000210 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000211 if (!num_per_line_option_set)
212 m_num_per_line = 32;
213 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000214 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000215 break;
216 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000217 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000218 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000219 if (!num_per_line_option_set)
220 m_num_per_line = 1;
221 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000222 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000223 break;
224 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000225 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000226 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000227 if (!num_per_line_option_set)
228 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000229 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000230 {
231 case 1:
232 case 2:
233 m_num_per_line = 8;
234 break;
235 case 4:
236 m_num_per_line = 4;
237 break;
238 case 8:
239 m_num_per_line = 2;
240 break;
241 default:
242 m_num_per_line = 1;
243 break;
244 }
245 }
246 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000247 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000248 break;
249
250 case eFormatVectorOfChar:
251 case eFormatVectorOfSInt8:
252 case eFormatVectorOfUInt8:
253 case eFormatVectorOfSInt16:
254 case eFormatVectorOfUInt16:
255 case eFormatVectorOfSInt32:
256 case eFormatVectorOfUInt32:
257 case eFormatVectorOfSInt64:
258 case eFormatVectorOfUInt64:
259 case eFormatVectorOfFloat32:
260 case eFormatVectorOfFloat64:
261 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000262 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000263 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000264 if (!num_per_line_option_set)
265 m_num_per_line = 1;
266 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000267 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000268 break;
269 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000270 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000271 }
272
Greg Clayton82f4cf42011-10-26 04:32:38 +0000273 bool
274 AnyOptionWasSet () const
275 {
276 return m_num_per_line.OptionWasSet() ||
277 m_output_as_binary ||
278 m_view_as_type.OptionWasSet();
279 }
280
Greg Clayton84c39662011-04-27 22:04:39 +0000281 OptionValueUInt64 m_num_per_line;
282 bool m_output_as_binary;
283 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000284 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000285};
286
287
288
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000289//----------------------------------------------------------------------
290// Read memory from the inferior process
291//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000292class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293{
294public:
295
Greg Claytona7015092010-09-18 01:14:36 +0000296 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000297 CommandObjectParsed (interpreter,
298 "memory read",
299 "Read from the memory of the process being debugged.",
300 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000301 eFlagRequiresTarget | eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000302 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000303 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000304 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000305 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000306 m_varobj_options(),
307 m_next_addr(LLDB_INVALID_ADDRESS),
308 m_prev_byte_size(0),
309 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
310 m_prev_memory_options (),
311 m_prev_outfile_options (),
312 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000313 {
Caroline Tice405fe672010-10-04 22:28:36 +0000314 CommandArgumentEntry arg1;
315 CommandArgumentEntry arg2;
316 CommandArgumentData start_addr_arg;
317 CommandArgumentData end_addr_arg;
318
319 // Define the first (and only) variant of this arg.
320 start_addr_arg.arg_type = eArgTypeStartAddress;
321 start_addr_arg.arg_repetition = eArgRepeatPlain;
322
323 // There is only one variant this argument could be; put it into the argument entry.
324 arg1.push_back (start_addr_arg);
325
326 // Define the first (and only) variant of this arg.
327 end_addr_arg.arg_type = eArgTypeEndAddress;
328 end_addr_arg.arg_repetition = eArgRepeatOptional;
329
330 // There is only one variant this argument could be; put it into the argument entry.
331 arg2.push_back (end_addr_arg);
332
333 // Push the data for the first argument into the m_arguments vector.
334 m_arguments.push_back (arg1);
335 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000336
Greg Clayton1deb7962011-10-25 06:44:01 +0000337 // Add the "--format" and "--count" options to group 1 and 3
338 m_option_group.Append (&m_format_options,
339 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000340 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000341 m_option_group.Append (&m_format_options,
342 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000343 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000344 // Add the "--size" option to group 1 and 2
345 m_option_group.Append (&m_format_options,
346 OptionGroupFormat::OPTION_GROUP_SIZE,
347 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000348 m_option_group.Append (&m_memory_options);
349 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton68ebae62011-04-28 20:55:26 +0000350 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000351 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000352 }
353
354 virtual
355 ~CommandObjectMemoryRead ()
356 {
357 }
358
359 Options *
360 GetOptions ()
361 {
Greg Clayton84c39662011-04-27 22:04:39 +0000362 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000363 }
364
Greg Clayton82f4cf42011-10-26 04:32:38 +0000365 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
366 {
367 return m_cmd_name.c_str();
368 }
369
Jim Ingham5a988412012-06-08 21:56:10 +0000370protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000371 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000372 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000373 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000374 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
375 Target *target = m_exe_ctx.GetTargetPtr();
376
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000377 const size_t argc = command.GetArgumentCount();
378
Greg Clayton82f4cf42011-10-26 04:32:38 +0000379 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000381 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
Greg Clayton2e1f7452012-12-15 02:08:17 +0000382 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000383 result.SetStatus(eReturnStatusFailed);
384 return false;
385 }
386
Greg Clayton68ebae62011-04-28 20:55:26 +0000387 ClangASTType clang_ast_type;
388 Error error;
389
Greg Clayton84c39662011-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 Lattner30fdc8d2010-06-08 16:52:24 +0000392 {
Greg Clayton84c39662011-04-27 22:04:39 +0000393 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000394
Greg Clayton84c39662011-04-27 22:04:39 +0000395 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000396 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000397 TypeList type_list;
398 uint32_t reference_count = 0;
399 uint32_t pointer_count = 0;
400 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000401
402#define ALL_KEYWORDS \
403 KEYWORD("const") \
404 KEYWORD("volatile") \
405 KEYWORD("restrict") \
406 KEYWORD("struct") \
407 KEYWORD("class") \
408 KEYWORD("union")
409
410#define KEYWORD(s) s,
411 static const char *g_keywords[] =
412 {
413 ALL_KEYWORDS
414 };
415#undef KEYWORD
416
417#define KEYWORD(s) (sizeof(s) - 1),
418 static const int g_keyword_lengths[] =
419 {
420 ALL_KEYWORDS
421 };
422#undef KEYWORD
423
424#undef ALL_KEYWORDS
425
426 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000427 std::string type_str(view_as_type_cstr);
428
429 // Remove all instances of g_keywords that are followed by spaces
430 for (size_t i = 0; i < g_num_keywords; ++i)
431 {
432 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000433 int keyword_len = g_keyword_lengths[i];
434
435 idx = 0;
436 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000437 {
438 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000439 {
Greg Clayton84c39662011-04-27 22:04:39 +0000440 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000441 idx = 0;
442 }
443 else
444 {
445 idx += keyword_len;
446 }
Greg Clayton84c39662011-04-27 22:04:39 +0000447 }
448 }
449 bool done = type_str.empty();
450 //
451 idx = type_str.find_first_not_of (" \t");
452 if (idx > 0 && idx != std::string::npos)
453 type_str.erase (0, idx);
454 while (!done)
455 {
456 // Strip trailing spaces
457 if (type_str.empty())
458 done = true;
459 else
460 {
461 switch (type_str[type_str.size()-1])
462 {
463 case '*':
464 ++pointer_count;
465 // fall through...
466 case ' ':
467 case '\t':
468 type_str.erase(type_str.size()-1);
469 break;
470
471 case '&':
472 if (reference_count == 0)
473 {
474 reference_count = 1;
475 type_str.erase(type_str.size()-1);
476 }
477 else
478 {
479 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
480 result.SetStatus(eReturnStatusFailed);
481 return false;
482 }
483 break;
484
485 default:
486 done = true;
487 break;
488 }
489 }
490 }
491
492 ConstString lookup_type_name(type_str.c_str());
Greg Claytonf9fc6092013-01-09 19:44:40 +0000493 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000494 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000495 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000496 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000497 if (sc.module_sp)
498 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000499 sc.module_sp->FindTypes (sc,
500 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000501 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000502 1,
503 type_list);
504 }
505 }
506 if (type_list.GetSize() == 0)
507 {
Greg Clayton29399a22012-04-06 17:41:13 +0000508 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000509 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000510 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000511 1,
512 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000513 }
514
515 if (type_list.GetSize() == 0)
516 {
517 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
518 lookup_type_name.GetCString(),
519 view_as_type_cstr);
520 result.SetStatus(eReturnStatusFailed);
521 return false;
522 }
523
524 TypeSP type_sp (type_list.GetTypeAtIndex(0));
525 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
526
527 while (pointer_count > 0)
528 {
529 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
530 if (pointer_type)
531 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
532 else
533 {
534 result.AppendError ("unable make a pointer type\n");
535 result.SetStatus(eReturnStatusFailed);
536 return false;
537 }
538 --pointer_count;
539 }
540
Greg Clayton1deb7962011-10-25 06:44:01 +0000541 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000542
Greg Clayton1deb7962011-10-25 06:44:01 +0000543 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000544 {
545 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
546 view_as_type_cstr);
547 result.SetStatus(eReturnStatusFailed);
548 return false;
549 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000550
Greg Clayton1deb7962011-10-25 06:44:01 +0000551 if (!m_format_options.GetCountValue().OptionWasSet())
552 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000553 }
554 else
555 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000556 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000557 }
558
559 // Look for invalid combinations of settings
560 if (error.Fail())
561 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000562 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000563 result.SetStatus(eReturnStatusFailed);
564 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000565 }
566
Greg Clayton82f4cf42011-10-26 04:32:38 +0000567 lldb::addr_t addr;
568 size_t total_byte_size = 0;
569 if (argc == 0)
570 {
571 // Use the last address and byte size and all options as they were
572 // if no options have been set
573 addr = m_next_addr;
574 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000575 clang_ast_type = m_prev_clang_ast_type;
576 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000577 !m_memory_options.AnyOptionWasSet() &&
578 !m_outfile_options.AnyOptionWasSet() &&
579 !m_varobj_options.AnyOptionWasSet())
580 {
581 m_format_options = m_prev_format_options;
582 m_memory_options = m_prev_memory_options;
583 m_outfile_options = m_prev_outfile_options;
584 m_varobj_options = m_prev_varobj_options;
585 }
586 }
587
Greg Clayton1deb7962011-10-25 06:44:01 +0000588 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
589 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000590 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000591
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000592 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000593 {
594 total_byte_size = item_count * item_byte_size;
595 if (total_byte_size == 0)
596 total_byte_size = 32;
597 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000598
Greg Clayton82f4cf42011-10-26 04:32:38 +0000599 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000600 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000601
602 if (addr == LLDB_INVALID_ADDRESS)
603 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000604 result.AppendError("invalid start address expression.");
605 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000606 result.SetStatus(eReturnStatusFailed);
607 return false;
608 }
609
610 if (argc == 2)
611 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000612 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000613 if (end_addr == LLDB_INVALID_ADDRESS)
614 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000615 result.AppendError("invalid end address expression.");
616 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000617 result.SetStatus(eReturnStatusFailed);
618 return false;
619 }
620 else if (end_addr <= addr)
621 {
Daniel Malead01b2952012-11-29 21:49:15 +0000622 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000623 result.SetStatus(eReturnStatusFailed);
624 return false;
625 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000626 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000627 {
Daniel Malead01b2952012-11-29 21:49:15 +0000628 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000629 result.SetStatus(eReturnStatusFailed);
630 return false;
631 }
632
633 total_byte_size = end_addr - addr;
634 item_count = total_byte_size / item_byte_size;
635 }
Greg Clayton84c39662011-04-27 22:04:39 +0000636
Sean Callanan1276c332012-04-28 01:27:38 +0000637 if (total_byte_size > 1024 && !m_memory_options.m_force)
638 {
639 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
640 result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
641 return false;
642 }
643
Greg Clayton84c39662011-04-27 22:04:39 +0000644 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000645 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000646 if (clang_ast_type.GetOpaqueQualType())
647 {
648 // Make sure we don't display our type as ASCII bytes like the default memory read
649 if (m_format_options.GetFormatValue().OptionWasSet() == false)
650 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
651
652 bytes_read = clang_ast_type.GetTypeByteSize() * m_format_options.GetCountValue().GetCurrentValue();
653 }
654 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000655 {
Greg Clayton84c39662011-04-27 22:04:39 +0000656 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Claytone72dfb32012-02-24 01:59:29 +0000657 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000658 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000659 if (bytes_read == 0)
660 {
Greg Clayton57f06302012-05-25 17:05:55 +0000661 const char *error_cstr = error.AsCString();
662 if (error_cstr && error_cstr[0])
663 {
664 result.AppendError(error_cstr);
665 }
666 else
667 {
Daniel Malead01b2952012-11-29 21:49:15 +0000668 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000669 }
Greg Clayton84c39662011-04-27 22:04:39 +0000670 result.SetStatus(eReturnStatusFailed);
671 return false;
672 }
673
674 if (bytes_read < total_byte_size)
Greg Claytonb9d5df52012-12-06 22:49:16 +0000675 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".", bytes_read, total_byte_size, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000676 }
677
Greg Clayton2e1f7452012-12-15 02:08:17 +0000678 m_next_addr = addr + bytes_read;
679 m_prev_byte_size = bytes_read;
680 m_prev_format_options = m_format_options;
681 m_prev_memory_options = m_memory_options;
682 m_prev_outfile_options = m_outfile_options;
683 m_prev_varobj_options = m_varobj_options;
684 m_prev_clang_ast_type = clang_ast_type;
685
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000686 StreamFile outfile_stream;
687 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000688 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
689 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000690 {
691 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000692 outfile_spec.GetPath (path, sizeof(path));
693
694 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
695 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
696 if (append)
697 open_options |= File::eOpenOptionAppend;
698
699 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000700 {
Greg Clayton84c39662011-04-27 22:04:39 +0000701 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000702 {
703 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
704 if (bytes_written > 0)
705 {
706 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
707 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000708 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000709 path);
710 return true;
711 }
712 else
713 {
Daniel Malead01b2952012-11-29 21:49:15 +0000714 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000715 result.SetStatus(eReturnStatusFailed);
716 return false;
717 }
718 }
719 else
720 {
721 // We are going to write ASCII to the file just point the
722 // output_stream to our outfile_stream...
723 output_stream = &outfile_stream;
724 }
725 }
726 else
727 {
Greg Clayton84c39662011-04-27 22:04:39 +0000728 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000729 result.SetStatus(eReturnStatusFailed);
730 return false;
731 }
732 }
733 else
734 {
735 output_stream = &result.GetOutputStream();
736 }
737
Greg Clayton84c39662011-04-27 22:04:39 +0000738
Greg Claytonf9fc6092013-01-09 19:44:40 +0000739 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000740 if (clang_ast_type.GetOpaqueQualType())
741 {
742 for (uint32_t i = 0; i<item_count; ++i)
743 {
744 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000745 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000746 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000747 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000748 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000749 name_strm.GetString().c_str(),
750 address,
751 clang_ast_type));
752 if (valobj_sp)
753 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000754 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000755 if (format != eFormatDefault)
756 valobj_sp->SetFormat (format);
757
Greg Clayton68ebae62011-04-28 20:55:26 +0000758 bool scope_already_checked = true;
Greg Clayton84c39662011-04-27 22:04:39 +0000759
Enrico Granata0c489f52012-03-01 04:24:26 +0000760 ValueObject::DumpValueObjectOptions options;
761 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
762 .SetMaximumDepth(m_varobj_options.max_depth)
763 .SetShowLocation(m_varobj_options.show_location)
764 .SetShowTypes(m_varobj_options.show_types)
765 .SetUseObjectiveC(m_varobj_options.use_objc)
766 .SetScopeChecked(scope_already_checked)
767 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granata86cc9822012-03-19 22:58:49 +0000768 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata0c489f52012-03-01 04:24:26 +0000769 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
770 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
771 .SetFormat(format)
772 .SetSummary();
Greg Clayton84c39662011-04-27 22:04:39 +0000773 ValueObject::DumpValueObject (*output_stream,
774 valobj_sp.get(),
Enrico Granata0c489f52012-03-01 04:24:26 +0000775 options);
Greg Clayton84c39662011-04-27 22:04:39 +0000776 }
777 else
778 {
779 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
780 view_as_type_cstr,
781 name_strm.GetString().c_str());
782 result.SetStatus(eReturnStatusFailed);
783 return false;
784 }
785 }
786 return true;
787 }
788
789 result.SetStatus(eReturnStatusSuccessFinishResult);
790 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000791 target->GetArchitecture().GetByteOrder(),
792 target->GetArchitecture().GetAddressByteSize());
Greg Clayton84c39662011-04-27 22:04:39 +0000793
794
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000795 assert (output_stream);
Greg Clayton1848afb2011-10-28 23:44:55 +0000796 uint32_t bytes_dumped = data.Dump (output_stream,
797 0,
798 m_format_options.GetFormat(),
799 item_byte_size,
800 item_count,
801 num_per_line,
802 addr,
803 0,
804 0,
805 exe_scope);
806 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000807 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000808 return true;
809 }
810
Greg Clayton84c39662011-04-27 22:04:39 +0000811 OptionGroupOptions m_option_group;
812 OptionGroupFormat m_format_options;
813 OptionGroupReadMemory m_memory_options;
814 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000815 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000816 lldb::addr_t m_next_addr;
817 lldb::addr_t m_prev_byte_size;
818 OptionGroupFormat m_prev_format_options;
819 OptionGroupReadMemory m_prev_memory_options;
820 OptionGroupOutputFile m_prev_outfile_options;
821 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000822 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000823};
824
Greg Clayton1deb7962011-10-25 06:44:01 +0000825
826OptionDefinition
827g_memory_write_option_table[] =
828{
829{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
830{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
831};
832
833
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000834//----------------------------------------------------------------------
835// Write memory to the inferior process
836//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000837class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000838{
839public:
840
Greg Clayton1deb7962011-10-25 06:44:01 +0000841 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000842 {
843 public:
Greg Clayton1deb7962011-10-25 06:44:01 +0000844 OptionGroupWriteMemory () :
845 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000846 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000847 }
848
849 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +0000850 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000851 {
852 }
853
Greg Clayton1deb7962011-10-25 06:44:01 +0000854 virtual uint32_t
855 GetNumDefinitions ()
856 {
857 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
858 }
859
860 virtual const OptionDefinition*
861 GetDefinitions ()
862 {
863 return g_memory_write_option_table;
864 }
865
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000866 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000867 SetOptionValue (CommandInterpreter &interpreter,
868 uint32_t option_idx,
869 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000870 {
871 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000872 const int short_option = g_memory_write_option_table[option_idx].short_option;
Greg Clayton1deb7962011-10-25 06:44:01 +0000873
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000874 switch (short_option)
875 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000876 case 'i':
877 m_infile.SetFile (option_arg, true);
878 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000879 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000880 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +0000881 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000882 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000883 break;
884
885 case 'o':
886 {
887 bool success;
888 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
889 if (!success)
890 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000891 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +0000892 }
893 }
894 break;
895
896 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000897 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +0000898 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000899 }
900 return error;
901 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000902
903 virtual void
904 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000905 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000906 m_infile.Clear();
907 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000908 }
909
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000910 FileSpec m_infile;
911 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000912 };
913
Greg Claytona7015092010-09-18 01:14:36 +0000914 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000915 CommandObjectParsed (interpreter,
916 "memory write",
917 "Write to the memory of the process being debugged.",
918 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000919 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +0000920 m_option_group (interpreter),
921 m_format_options (eFormatBytes, 1, UINT64_MAX),
922 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000923 {
Caroline Tice405fe672010-10-04 22:28:36 +0000924 CommandArgumentEntry arg1;
925 CommandArgumentEntry arg2;
926 CommandArgumentData addr_arg;
927 CommandArgumentData value_arg;
928
929 // Define the first (and only) variant of this arg.
930 addr_arg.arg_type = eArgTypeAddress;
931 addr_arg.arg_repetition = eArgRepeatPlain;
932
933 // There is only one variant this argument could be; put it into the argument entry.
934 arg1.push_back (addr_arg);
935
936 // Define the first (and only) variant of this arg.
937 value_arg.arg_type = eArgTypeValue;
938 value_arg.arg_repetition = eArgRepeatPlus;
939
940 // There is only one variant this argument could be; put it into the argument entry.
941 arg2.push_back (value_arg);
942
943 // Push the data for the first argument into the m_arguments vector.
944 m_arguments.push_back (arg1);
945 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +0000946
947 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
948 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
949 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
950 m_option_group.Finalize();
951
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000952 }
953
954 virtual
955 ~CommandObjectMemoryWrite ()
956 {
957 }
958
959 Options *
960 GetOptions ()
961 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000962 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000963 }
964
965 bool
966 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
967 {
968 if (total_byte_size > 8)
969 return false;
970
971 if (total_byte_size == 8)
972 return true;
973
974 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
975 return uval64 <= max;
976 }
977
978 bool
979 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
980 {
981 if (total_byte_size > 8)
982 return false;
983
984 if (total_byte_size == 8)
985 return true;
986
987 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
988 const int64_t min = ~(max);
989 return min <= sval64 && sval64 <= max;
990 }
991
Jim Ingham5a988412012-06-08 21:56:10 +0000992protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000993 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +0000994 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000995 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000996 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
997 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000998
999 const size_t argc = command.GetArgumentCount();
1000
Greg Clayton1deb7962011-10-25 06:44:01 +00001001 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001002 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001003 if (argc < 1)
1004 {
1005 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1006 result.SetStatus(eReturnStatusFailed);
1007 return false;
1008 }
1009 }
1010 else if (argc < 2)
1011 {
1012 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001013 result.SetStatus(eReturnStatusFailed);
1014 return false;
1015 }
1016
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001017 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001018 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1019 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001020
Greg Clayton1deb7962011-10-25 06:44:01 +00001021 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1022 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001023
Greg Claytonb9d5df52012-12-06 22:49:16 +00001024 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001025 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001026 command.GetArgumentAtIndex(0),
1027 LLDB_INVALID_ADDRESS,
1028 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001029
1030 if (addr == LLDB_INVALID_ADDRESS)
1031 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001032 result.AppendError("invalid address expression\n");
1033 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001034 result.SetStatus(eReturnStatusFailed);
1035 return false;
1036 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001037
Greg Clayton1deb7962011-10-25 06:44:01 +00001038 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001039 {
1040 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +00001041 if (item_byte_size > 0)
1042 length = item_byte_size;
1043 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001044 if (data_sp)
1045 {
1046 length = data_sp->GetByteSize();
1047 if (length > 0)
1048 {
1049 Error error;
1050 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1051
1052 if (bytes_written == length)
1053 {
1054 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001055 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001056 result.SetStatus(eReturnStatusSuccessFinishResult);
1057 }
1058 else if (bytes_written > 0)
1059 {
1060 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001061 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001062 result.SetStatus(eReturnStatusSuccessFinishResult);
1063 }
1064 else
1065 {
Daniel Malead01b2952012-11-29 21:49:15 +00001066 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001067 result.SetStatus(eReturnStatusFailed);
1068 }
1069 }
1070 }
1071 else
1072 {
1073 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1074 result.SetStatus(eReturnStatusFailed);
1075 }
1076 return result.Succeeded();
1077 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001078 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001079 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001080 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001081 item_byte_size = buffer.GetAddressByteSize();
1082 else
1083 item_byte_size = 1;
1084 }
1085
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001086 command.Shift(); // shift off the address argument
1087 uint64_t uval64;
1088 int64_t sval64;
1089 bool success = false;
1090 const uint32_t num_value_args = command.GetArgumentCount();
1091 uint32_t i;
1092 for (i=0; i<num_value_args; ++i)
1093 {
1094 const char *value_str = command.GetArgumentAtIndex(i);
1095
Greg Clayton1deb7962011-10-25 06:44:01 +00001096 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001097 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001098 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001099 case eFormatFloat: // TODO: add support for floats soon
1100 case eFormatCharPrintable:
1101 case eFormatBytesWithASCII:
1102 case eFormatComplex:
1103 case eFormatEnum:
1104 case eFormatUnicode16:
1105 case eFormatUnicode32:
1106 case eFormatVectorOfChar:
1107 case eFormatVectorOfSInt8:
1108 case eFormatVectorOfUInt8:
1109 case eFormatVectorOfSInt16:
1110 case eFormatVectorOfUInt16:
1111 case eFormatVectorOfSInt32:
1112 case eFormatVectorOfUInt32:
1113 case eFormatVectorOfSInt64:
1114 case eFormatVectorOfUInt64:
1115 case eFormatVectorOfFloat32:
1116 case eFormatVectorOfFloat64:
1117 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001118 case eFormatOSType:
1119 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001120 case eFormatAddressInfo:
1121 case eFormatHexFloat:
1122 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001123 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001124 result.AppendError("unsupported format for writing memory");
1125 result.SetStatus(eReturnStatusFailed);
1126 return false;
1127
1128 case eFormatDefault:
1129 case eFormatBytes:
1130 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001131 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001132 case eFormatPointer:
1133
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001134 // Decode hex bytes
1135 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1136 if (!success)
1137 {
1138 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1139 result.SetStatus(eReturnStatusFailed);
1140 return false;
1141 }
1142 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1143 {
Daniel Malead01b2952012-11-29 21:49:15 +00001144 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001145 result.SetStatus(eReturnStatusFailed);
1146 return false;
1147 }
1148 buffer.PutMaxHex64 (uval64, item_byte_size);
1149 break;
1150
1151 case eFormatBoolean:
1152 uval64 = Args::StringToBoolean(value_str, false, &success);
1153 if (!success)
1154 {
1155 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1156 result.SetStatus(eReturnStatusFailed);
1157 return false;
1158 }
1159 buffer.PutMaxHex64 (uval64, item_byte_size);
1160 break;
1161
1162 case eFormatBinary:
1163 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1164 if (!success)
1165 {
1166 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1167 result.SetStatus(eReturnStatusFailed);
1168 return false;
1169 }
1170 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1171 {
Daniel Malead01b2952012-11-29 21:49:15 +00001172 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001173 result.SetStatus(eReturnStatusFailed);
1174 return false;
1175 }
1176 buffer.PutMaxHex64 (uval64, item_byte_size);
1177 break;
1178
Greg Clayton4e4294b2011-06-17 23:50:44 +00001179 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001180 case eFormatChar:
1181 case eFormatCString:
1182 if (value_str[0])
1183 {
1184 size_t len = strlen (value_str);
1185 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001186 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001187 ++len;
1188 Error error;
1189 if (process->WriteMemory (addr, value_str, len, error) == len)
1190 {
1191 addr += len;
1192 }
1193 else
1194 {
Daniel Malead01b2952012-11-29 21:49:15 +00001195 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001196 result.SetStatus(eReturnStatusFailed);
1197 return false;
1198 }
1199 }
1200 break;
1201
1202 case eFormatDecimal:
1203 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1204 if (!success)
1205 {
1206 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1207 result.SetStatus(eReturnStatusFailed);
1208 return false;
1209 }
1210 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1211 {
Daniel Malead01b2952012-11-29 21:49:15 +00001212 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001213 result.SetStatus(eReturnStatusFailed);
1214 return false;
1215 }
1216 buffer.PutMaxHex64 (sval64, item_byte_size);
1217 break;
1218
1219 case eFormatUnsigned:
1220 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1221 if (!success)
1222 {
1223 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1224 result.SetStatus(eReturnStatusFailed);
1225 return false;
1226 }
1227 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1228 {
Daniel Malead01b2952012-11-29 21:49:15 +00001229 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001230 result.SetStatus(eReturnStatusFailed);
1231 return false;
1232 }
1233 buffer.PutMaxHex64 (uval64, item_byte_size);
1234 break;
1235
1236 case eFormatOctal:
1237 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1238 if (!success)
1239 {
1240 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1241 result.SetStatus(eReturnStatusFailed);
1242 return false;
1243 }
1244 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1245 {
Daniel Malead01b2952012-11-29 21:49:15 +00001246 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001247 result.SetStatus(eReturnStatusFailed);
1248 return false;
1249 }
1250 buffer.PutMaxHex64 (uval64, item_byte_size);
1251 break;
1252 }
1253 }
1254
1255 if (!buffer.GetString().empty())
1256 {
1257 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001258 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001259 return true;
1260 else
1261 {
Daniel Malead01b2952012-11-29 21:49:15 +00001262 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001263 result.SetStatus(eReturnStatusFailed);
1264 return false;
1265 }
1266 }
1267 return true;
1268 }
1269
Greg Clayton1deb7962011-10-25 06:44:01 +00001270 OptionGroupOptions m_option_group;
1271 OptionGroupFormat m_format_options;
1272 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001273};
1274
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001275
1276//-------------------------------------------------------------------------
1277// CommandObjectMemory
1278//-------------------------------------------------------------------------
1279
Greg Clayton66111032010-06-23 01:19:29 +00001280CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001281 CommandObjectMultiword (interpreter,
1282 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001283 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001284 "memory <subcommand> [<subcommand-options>]")
1285{
Greg Claytona7015092010-09-18 01:14:36 +00001286 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1287 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001288}
1289
1290CommandObjectMemory::~CommandObjectMemory ()
1291{
1292}