blob: 77186a2be2d23e77d5837fb50030bb30df841529 [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
Virgile Bellobdae3782013-08-28 12:14:27 +000015#include <inttypes.h>
16
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017// C++ Includes
18// Other libraries and framework includes
19// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Core/DataBufferHeap.h"
21#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000022#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000023#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000025#include "lldb/Core/ValueObjectMemory.h"
Enrico Granata4d93b8c2013-09-30 19:11:51 +000026#include "lldb/DataFormatters/ValueObjectPrinter.h"
Greg Clayton66111032010-06-23 01:19:29 +000027#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000029#include "lldb/Interpreter/CommandInterpreter.h"
30#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000031#include "lldb/Interpreter/OptionGroupFormat.h"
32#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000033#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000034#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton1f746072012-08-29 21:13:06 +000035#include "lldb/Symbol/TypeList.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036#include "lldb/Target/Process.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000037#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038
39using namespace lldb;
40using namespace lldb_private;
41
Greg Clayton68ebae62011-04-28 20:55:26 +000042static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000043g_option_table[] =
44{
Virgile Belloe2607b52013-09-05 16:42:23 +000045 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
46 { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , 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."},
47 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton2346fcf2012-11-02 21:14:58 +000048 { LLDB_OPT_SET_1|
49 LLDB_OPT_SET_2|
Virgile Belloe2607b52013-09-05 16:42:23 +000050 LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
Greg Clayton84c39662011-04-27 22:04:39 +000051};
52
53
54
55class OptionGroupReadMemory : public OptionGroup
56{
57public:
58
59 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000060 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000061 m_output_as_binary (false),
62 m_view_as_type()
63 {
64 }
65
66 virtual
67 ~OptionGroupReadMemory ()
68 {
69 }
70
71
72 virtual uint32_t
73 GetNumDefinitions ()
74 {
75 return sizeof (g_option_table) / sizeof (OptionDefinition);
76 }
77
78 virtual const OptionDefinition*
79 GetDefinitions ()
80 {
81 return g_option_table;
82 }
83
84 virtual Error
85 SetOptionValue (CommandInterpreter &interpreter,
86 uint32_t option_idx,
87 const char *option_arg)
88 {
89 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000090 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000091
92 switch (short_option)
93 {
94 case 'l':
95 error = m_num_per_line.SetValueFromCString (option_arg);
96 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +000097 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +000098 break;
Greg Clayton1deb7962011-10-25 06:44:01 +000099
Greg Clayton84c39662011-04-27 22:04:39 +0000100 case 'b':
101 m_output_as_binary = true;
102 break;
103
104 case 't':
105 error = m_view_as_type.SetValueFromCString (option_arg);
106 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000107
108 case 'r':
109 m_force = true;
110 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000111
112 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000113 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000114 break;
115 }
116 return error;
117 }
118
119 virtual void
120 OptionParsingStarting (CommandInterpreter &interpreter)
121 {
Greg Clayton84c39662011-04-27 22:04:39 +0000122 m_num_per_line.Clear();
123 m_output_as_binary = false;
124 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000125 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000126 }
127
Greg Clayton68ebae62011-04-28 20:55:26 +0000128 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000129 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000130 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000131 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000132 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
133 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000134 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000135 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000136 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000137
Greg Clayton68ebae62011-04-28 20:55:26 +0000138 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000139 {
140 default:
141 break;
142
143 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000144 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000145 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000146 if (!num_per_line_option_set)
147 m_num_per_line = 1;
148 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000149 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000150 break;
151
152 case eFormatCString:
153 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000154
155 case eFormatInstruction:
156 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000157 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000158 m_num_per_line = 1;
159 break;
160
161 case eFormatAddressInfo:
162 if (!byte_size_option_set)
163 byte_size_value = target->GetArchitecture().GetAddressByteSize();
164 m_num_per_line = 1;
165 if (!count_option_set)
166 format_options.GetCountValue() = 8;
167 break;
168
Greg Clayton84c39662011-04-27 22:04:39 +0000169 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000170 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000171 if (!num_per_line_option_set)
172 m_num_per_line = 4;
173 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000174 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000175 break;
176
177 case eFormatBinary:
178 case eFormatFloat:
179 case eFormatOctal:
180 case eFormatDecimal:
181 case eFormatEnum:
182 case eFormatUnicode16:
183 case eFormatUnicode32:
184 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000185 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000186 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000187 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000188 if (!num_per_line_option_set)
189 m_num_per_line = 1;
190 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000191 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000192 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000193
Greg Clayton84c39662011-04-27 22:04:39 +0000194 case eFormatBytes:
195 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000196 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000197 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000198 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000199 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000200 "\tconsider using a different display format or don't specify the byte size",
201 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000202 }
203 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000204 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000205 if (!num_per_line_option_set)
206 m_num_per_line = 16;
207 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000208 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000209 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000210 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000211 case eFormatChar:
212 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000213 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000214 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000215 if (!num_per_line_option_set)
216 m_num_per_line = 32;
217 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000218 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000219 break;
220 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000221 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000222 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000223 if (!num_per_line_option_set)
224 m_num_per_line = 1;
225 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000226 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000227 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000228 case eFormatComplexInteger:
229 if (!byte_size_option_set)
230 byte_size_value = 8;
231 if (!num_per_line_option_set)
232 m_num_per_line = 1;
233 if (!count_option_set)
234 format_options.GetCountValue() = 8;
235 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000236 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000237 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000238 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000239 if (!num_per_line_option_set)
240 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000241 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000242 {
243 case 1:
244 case 2:
245 m_num_per_line = 8;
246 break;
247 case 4:
248 m_num_per_line = 4;
249 break;
250 case 8:
251 m_num_per_line = 2;
252 break;
253 default:
254 m_num_per_line = 1;
255 break;
256 }
257 }
258 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000259 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000260 break;
261
262 case eFormatVectorOfChar:
263 case eFormatVectorOfSInt8:
264 case eFormatVectorOfUInt8:
265 case eFormatVectorOfSInt16:
266 case eFormatVectorOfUInt16:
267 case eFormatVectorOfSInt32:
268 case eFormatVectorOfUInt32:
269 case eFormatVectorOfSInt64:
270 case eFormatVectorOfUInt64:
271 case eFormatVectorOfFloat32:
272 case eFormatVectorOfFloat64:
273 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000274 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000275 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000276 if (!num_per_line_option_set)
277 m_num_per_line = 1;
278 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000279 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000280 break;
281 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000282 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000283 }
284
Greg Clayton82f4cf42011-10-26 04:32:38 +0000285 bool
286 AnyOptionWasSet () const
287 {
288 return m_num_per_line.OptionWasSet() ||
289 m_output_as_binary ||
290 m_view_as_type.OptionWasSet();
291 }
292
Greg Clayton84c39662011-04-27 22:04:39 +0000293 OptionValueUInt64 m_num_per_line;
294 bool m_output_as_binary;
295 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000296 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000297};
298
299
300
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000301//----------------------------------------------------------------------
302// Read memory from the inferior process
303//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000304class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305{
306public:
307
Greg Claytona7015092010-09-18 01:14:36 +0000308 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000309 CommandObjectParsed (interpreter,
310 "memory read",
311 "Read from the memory of the process being debugged.",
312 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000313 eFlagRequiresTarget | eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000314 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000315 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000316 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000317 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000318 m_varobj_options(),
319 m_next_addr(LLDB_INVALID_ADDRESS),
320 m_prev_byte_size(0),
321 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
322 m_prev_memory_options (),
323 m_prev_outfile_options (),
324 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325 {
Caroline Tice405fe672010-10-04 22:28:36 +0000326 CommandArgumentEntry arg1;
327 CommandArgumentEntry arg2;
328 CommandArgumentData start_addr_arg;
329 CommandArgumentData end_addr_arg;
330
331 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000332 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000333 start_addr_arg.arg_repetition = eArgRepeatPlain;
334
335 // There is only one variant this argument could be; put it into the argument entry.
336 arg1.push_back (start_addr_arg);
337
338 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000339 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000340 end_addr_arg.arg_repetition = eArgRepeatOptional;
341
342 // There is only one variant this argument could be; put it into the argument entry.
343 arg2.push_back (end_addr_arg);
344
345 // Push the data for the first argument into the m_arguments vector.
346 m_arguments.push_back (arg1);
347 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000348
Greg Clayton1deb7962011-10-25 06:44:01 +0000349 // Add the "--format" and "--count" options to group 1 and 3
350 m_option_group.Append (&m_format_options,
351 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000352 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000353 m_option_group.Append (&m_format_options,
354 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000355 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000356 // Add the "--size" option to group 1 and 2
357 m_option_group.Append (&m_format_options,
358 OptionGroupFormat::OPTION_GROUP_SIZE,
359 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000360 m_option_group.Append (&m_memory_options);
361 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 +0000362 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000363 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364 }
365
366 virtual
367 ~CommandObjectMemoryRead ()
368 {
369 }
370
371 Options *
372 GetOptions ()
373 {
Greg Clayton84c39662011-04-27 22:04:39 +0000374 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000375 }
376
Greg Clayton82f4cf42011-10-26 04:32:38 +0000377 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
378 {
379 return m_cmd_name.c_str();
380 }
381
Jim Ingham5a988412012-06-08 21:56:10 +0000382protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000383 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000384 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000386 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
387 Target *target = m_exe_ctx.GetTargetPtr();
388
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000389 const size_t argc = command.GetArgumentCount();
390
Greg Clayton82f4cf42011-10-26 04:32:38 +0000391 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000393 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 +0000394 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000395 result.SetStatus(eReturnStatusFailed);
396 return false;
397 }
398
Greg Clayton68ebae62011-04-28 20:55:26 +0000399 ClangASTType clang_ast_type;
400 Error error;
401
Greg Clayton84c39662011-04-27 22:04:39 +0000402 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
403 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000404 {
Greg Clayton84c39662011-04-27 22:04:39 +0000405 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000406
Greg Clayton84c39662011-04-27 22:04:39 +0000407 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000408 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000409 TypeList type_list;
410 uint32_t reference_count = 0;
411 uint32_t pointer_count = 0;
412 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000413
414#define ALL_KEYWORDS \
415 KEYWORD("const") \
416 KEYWORD("volatile") \
417 KEYWORD("restrict") \
418 KEYWORD("struct") \
419 KEYWORD("class") \
420 KEYWORD("union")
421
422#define KEYWORD(s) s,
423 static const char *g_keywords[] =
424 {
425 ALL_KEYWORDS
426 };
427#undef KEYWORD
428
429#define KEYWORD(s) (sizeof(s) - 1),
430 static const int g_keyword_lengths[] =
431 {
432 ALL_KEYWORDS
433 };
434#undef KEYWORD
435
436#undef ALL_KEYWORDS
437
438 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000439 std::string type_str(view_as_type_cstr);
440
441 // Remove all instances of g_keywords that are followed by spaces
442 for (size_t i = 0; i < g_num_keywords; ++i)
443 {
444 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000445 int keyword_len = g_keyword_lengths[i];
446
447 idx = 0;
448 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000449 {
450 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000451 {
Greg Clayton84c39662011-04-27 22:04:39 +0000452 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000453 idx = 0;
454 }
455 else
456 {
457 idx += keyword_len;
458 }
Greg Clayton84c39662011-04-27 22:04:39 +0000459 }
460 }
461 bool done = type_str.empty();
462 //
463 idx = type_str.find_first_not_of (" \t");
464 if (idx > 0 && idx != std::string::npos)
465 type_str.erase (0, idx);
466 while (!done)
467 {
468 // Strip trailing spaces
469 if (type_str.empty())
470 done = true;
471 else
472 {
473 switch (type_str[type_str.size()-1])
474 {
475 case '*':
476 ++pointer_count;
477 // fall through...
478 case ' ':
479 case '\t':
480 type_str.erase(type_str.size()-1);
481 break;
482
483 case '&':
484 if (reference_count == 0)
485 {
486 reference_count = 1;
487 type_str.erase(type_str.size()-1);
488 }
489 else
490 {
491 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
492 result.SetStatus(eReturnStatusFailed);
493 return false;
494 }
495 break;
496
497 default:
498 done = true;
499 break;
500 }
501 }
502 }
503
504 ConstString lookup_type_name(type_str.c_str());
Jason Molendab57e4a12013-11-04 09:33:30 +0000505 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000506 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000507 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000508 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000509 if (sc.module_sp)
510 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000511 sc.module_sp->FindTypes (sc,
512 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000513 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000514 1,
515 type_list);
516 }
517 }
518 if (type_list.GetSize() == 0)
519 {
Greg Clayton29399a22012-04-06 17:41:13 +0000520 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000521 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000522 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000523 1,
524 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000525 }
526
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000527 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000528 {
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000529 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
530 if (tdecl)
531 {
532 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
533 }
Greg Clayton84c39662011-04-27 22:04:39 +0000534 }
535
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000536 if (clang_ast_type.IsValid() == false)
537 {
538 if (type_list.GetSize() == 0)
539 {
540 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
541 lookup_type_name.GetCString(),
542 view_as_type_cstr);
543 result.SetStatus(eReturnStatusFailed);
544 return false;
545 }
546 else
547 {
548 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton57ee3062013-07-11 22:46:58 +0000549 clang_ast_type = type_sp->GetClangFullType();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000550 }
551 }
Greg Clayton84c39662011-04-27 22:04:39 +0000552
553 while (pointer_count > 0)
554 {
Greg Clayton57ee3062013-07-11 22:46:58 +0000555 ClangASTType pointer_type = clang_ast_type.GetPointerType();
556 if (pointer_type.IsValid())
557 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000558 else
559 {
560 result.AppendError ("unable make a pointer type\n");
561 result.SetStatus(eReturnStatusFailed);
562 return false;
563 }
564 --pointer_count;
565 }
566
Greg Clayton57ee3062013-07-11 22:46:58 +0000567 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize();
Greg Clayton84c39662011-04-27 22:04:39 +0000568
Greg Clayton1deb7962011-10-25 06:44:01 +0000569 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000570 {
571 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
572 view_as_type_cstr);
573 result.SetStatus(eReturnStatusFailed);
574 return false;
575 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000576
Greg Clayton1deb7962011-10-25 06:44:01 +0000577 if (!m_format_options.GetCountValue().OptionWasSet())
578 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000579 }
580 else
581 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000582 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000583 }
584
585 // Look for invalid combinations of settings
586 if (error.Fail())
587 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000588 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000589 result.SetStatus(eReturnStatusFailed);
590 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000591 }
592
Greg Clayton82f4cf42011-10-26 04:32:38 +0000593 lldb::addr_t addr;
594 size_t total_byte_size = 0;
595 if (argc == 0)
596 {
597 // Use the last address and byte size and all options as they were
598 // if no options have been set
599 addr = m_next_addr;
600 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000601 clang_ast_type = m_prev_clang_ast_type;
602 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000603 !m_memory_options.AnyOptionWasSet() &&
604 !m_outfile_options.AnyOptionWasSet() &&
605 !m_varobj_options.AnyOptionWasSet())
606 {
607 m_format_options = m_prev_format_options;
608 m_memory_options = m_prev_memory_options;
609 m_outfile_options = m_prev_outfile_options;
610 m_varobj_options = m_prev_varobj_options;
611 }
612 }
613
Greg Clayton1deb7962011-10-25 06:44:01 +0000614 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000615 size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000616 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000617
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000618 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000619 {
620 total_byte_size = item_count * item_byte_size;
621 if (total_byte_size == 0)
622 total_byte_size = 32;
623 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000624
Greg Clayton82f4cf42011-10-26 04:32:38 +0000625 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000626 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000627
628 if (addr == LLDB_INVALID_ADDRESS)
629 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000630 result.AppendError("invalid start address expression.");
631 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000632 result.SetStatus(eReturnStatusFailed);
633 return false;
634 }
635
636 if (argc == 2)
637 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000638 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000639 if (end_addr == LLDB_INVALID_ADDRESS)
640 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000641 result.AppendError("invalid end address expression.");
642 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000643 result.SetStatus(eReturnStatusFailed);
644 return false;
645 }
646 else if (end_addr <= addr)
647 {
Daniel Malead01b2952012-11-29 21:49:15 +0000648 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 +0000649 result.SetStatus(eReturnStatusFailed);
650 return false;
651 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000652 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000653 {
Sylvestre Ledru779f9212013-10-31 23:55:19 +0000654 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %zu), not both.\n", end_addr, item_count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000655 result.SetStatus(eReturnStatusFailed);
656 return false;
657 }
658
659 total_byte_size = end_addr - addr;
660 item_count = total_byte_size / item_byte_size;
661 }
Greg Clayton84c39662011-04-27 22:04:39 +0000662
Enrico Granatad325bf92013-06-04 22:54:16 +0000663 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
664
665 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000666 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000667 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
668 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
669 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
Sean Callanan1276c332012-04-28 01:27:38 +0000670 return false;
671 }
672
Greg Clayton84c39662011-04-27 22:04:39 +0000673 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000674 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000675 if (clang_ast_type.GetOpaqueQualType())
676 {
677 // Make sure we don't display our type as ASCII bytes like the default memory read
678 if (m_format_options.GetFormatValue().OptionWasSet() == false)
679 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
680
Greg Clayton57ee3062013-07-11 22:46:58 +0000681 bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000682 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000683 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000684 {
Greg Clayton84c39662011-04-27 22:04:39 +0000685 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000686 if (data_sp->GetBytes() == NULL)
687 {
688 result.AppendErrorWithFormat ("can't allocate 0x%zx bytes for the memory read buffer, specify a smaller size to read", total_byte_size);
689 result.SetStatus(eReturnStatusFailed);
690 return false;
691 }
692
Greg Claytone72dfb32012-02-24 01:59:29 +0000693 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000694 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000695 if (bytes_read == 0)
696 {
Greg Clayton57f06302012-05-25 17:05:55 +0000697 const char *error_cstr = error.AsCString();
698 if (error_cstr && error_cstr[0])
699 {
700 result.AppendError(error_cstr);
701 }
702 else
703 {
Daniel Malead01b2952012-11-29 21:49:15 +0000704 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000705 }
Greg Clayton84c39662011-04-27 22:04:39 +0000706 result.SetStatus(eReturnStatusFailed);
707 return false;
708 }
709
710 if (bytes_read < total_byte_size)
Sylvestre Ledru779f9212013-10-31 23:55:19 +0000711 result.AppendWarningWithFormat("Not all bytes (%zu/%zu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000712 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000713 else
714 {
715 // we treat c-strings as a special case because they do not have a fixed size
716 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
717 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
718 else
719 item_byte_size = target->GetMaximumSizeOfStringSummary();
720 if (!m_format_options.GetCountValue().OptionWasSet())
721 item_count = 1;
722 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000723 if (data_sp->GetBytes() == NULL)
724 {
725 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx64 " bytes for the memory read buffer, specify a smaller size to read", (uint64_t)((item_byte_size+1) * item_count));
726 result.SetStatus(eReturnStatusFailed);
727 return false;
728 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000729 uint8_t *data_ptr = data_sp->GetBytes();
730 auto data_addr = addr;
731 auto count = item_count;
732 item_count = 0;
733 while (item_count < count)
734 {
735 std::string buffer;
736 buffer.resize(item_byte_size+1,0);
737 Error error;
738 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
739 if (error.Fail())
740 {
741 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
742 result.SetStatus(eReturnStatusFailed);
743 return false;
744 }
745 if (item_byte_size == read)
746 {
747 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
748 break;
749 }
750 read+=1; // account for final NULL byte
751 memcpy(data_ptr, &buffer[0], read);
752 data_ptr += read;
753 data_addr += read;
754 bytes_read += read;
755 item_count++; // if we break early we know we only read item_count strings
756 }
757 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
758 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000759
Greg Clayton2e1f7452012-12-15 02:08:17 +0000760 m_next_addr = addr + bytes_read;
761 m_prev_byte_size = bytes_read;
762 m_prev_format_options = m_format_options;
763 m_prev_memory_options = m_memory_options;
764 m_prev_outfile_options = m_outfile_options;
765 m_prev_varobj_options = m_varobj_options;
766 m_prev_clang_ast_type = clang_ast_type;
767
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000768 StreamFile outfile_stream;
769 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000770 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
771 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000772 {
773 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000774 outfile_spec.GetPath (path, sizeof(path));
775
776 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
777 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
778 if (append)
779 open_options |= File::eOpenOptionAppend;
780
781 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000782 {
Greg Clayton84c39662011-04-27 22:04:39 +0000783 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000784 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000785 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000786 if (bytes_written > 0)
787 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000788 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000789 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000790 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000791 path);
792 return true;
793 }
794 else
795 {
Daniel Malead01b2952012-11-29 21:49:15 +0000796 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000797 result.SetStatus(eReturnStatusFailed);
798 return false;
799 }
800 }
801 else
802 {
803 // We are going to write ASCII to the file just point the
804 // output_stream to our outfile_stream...
805 output_stream = &outfile_stream;
806 }
807 }
808 else
809 {
Greg Clayton84c39662011-04-27 22:04:39 +0000810 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000811 result.SetStatus(eReturnStatusFailed);
812 return false;
813 }
814 }
815 else
816 {
817 output_stream = &result.GetOutputStream();
818 }
819
Greg Clayton84c39662011-04-27 22:04:39 +0000820
Greg Claytonf9fc6092013-01-09 19:44:40 +0000821 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000822 if (clang_ast_type.GetOpaqueQualType())
823 {
824 for (uint32_t i = 0; i<item_count; ++i)
825 {
826 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000827 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000828 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000829 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000830 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000831 name_strm.GetString().c_str(),
832 address,
833 clang_ast_type));
834 if (valobj_sp)
835 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000836 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000837 if (format != eFormatDefault)
838 valobj_sp->SetFormat (format);
839
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000840 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000841
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000842 valobj_sp->Dump(*output_stream,options);
Greg Clayton84c39662011-04-27 22:04:39 +0000843 }
844 else
845 {
846 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
847 view_as_type_cstr,
848 name_strm.GetString().c_str());
849 result.SetStatus(eReturnStatusFailed);
850 return false;
851 }
852 }
853 return true;
854 }
855
856 result.SetStatus(eReturnStatusSuccessFinishResult);
857 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000858 target->GetArchitecture().GetByteOrder(),
859 target->GetArchitecture().GetAddressByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000860
861 Format format = m_format_options.GetFormat();
862 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
Enrico Granata0947a6e2013-10-29 23:04:29 +0000863 && (item_byte_size != 1))
Enrico Granata31898912013-05-21 17:39:04 +0000864 {
Enrico Granata0947a6e2013-10-29 23:04:29 +0000865 // if a count was not passed, or it is 1
866 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
867 {
868 // this turns requests such as
869 // memory read -fc -s10 -c1 *charPtrPtr
870 // which make no sense (what is a char of size 10?)
871 // into a request for fetching 10 chars of size 1 from the same memory location
872 format = eFormatCharArray;
873 item_count = item_byte_size;
874 item_byte_size = 1;
875 }
876 else
877 {
878 // here we passed a count, and it was not 1
879 // so we have a byte_size and a count
880 // we could well multiply those, but instead let's just fail
881 result.AppendErrorWithFormat("reading memory as characters of size %zu is not supported", item_byte_size);
882 result.SetStatus(eReturnStatusFailed);
883 return false;
884 }
Enrico Granata31898912013-05-21 17:39:04 +0000885 }
Greg Clayton84c39662011-04-27 22:04:39 +0000886
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000887 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000888 size_t bytes_dumped = data.Dump (output_stream,
889 0,
Enrico Granata31898912013-05-21 17:39:04 +0000890 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000891 item_byte_size,
892 item_count,
893 num_per_line,
894 addr,
895 0,
896 0,
897 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000898 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000899 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000900 return true;
901 }
902
Greg Clayton84c39662011-04-27 22:04:39 +0000903 OptionGroupOptions m_option_group;
904 OptionGroupFormat m_format_options;
905 OptionGroupReadMemory m_memory_options;
906 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000907 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000908 lldb::addr_t m_next_addr;
909 lldb::addr_t m_prev_byte_size;
910 OptionGroupFormat m_prev_format_options;
911 OptionGroupReadMemory m_prev_memory_options;
912 OptionGroupOutputFile m_prev_outfile_options;
913 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000914 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000915};
916
Enrico Granata53468432013-11-13 02:18:44 +0000917OptionDefinition
918g_memory_find_option_table[] =
919{
920 { LLDB_OPT_SET_1, false, "expr", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
921 { LLDB_OPT_SET_1, false, "string", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
922 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many times to perform the search."},
923 { LLDB_OPT_SET_1, false, "do-read", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Should we do a memory read at each match."},
924};
925
926
927//----------------------------------------------------------------------
928// Find the specified data in memory
929//----------------------------------------------------------------------
930class CommandObjectMemoryFind : public CommandObjectParsed
931{
932public:
933
934 class OptionGroupFindMemory : public OptionGroup
935 {
936 public:
937 OptionGroupFindMemory () :
938 OptionGroup(),
939 m_count(1),
940 m_do_read(false)
941 {
942 }
943
944 virtual
945 ~OptionGroupFindMemory ()
946 {
947 }
948
949 virtual uint32_t
950 GetNumDefinitions ()
951 {
952 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
953 }
954
955 virtual const OptionDefinition*
956 GetDefinitions ()
957 {
958 return g_memory_find_option_table;
959 }
960
961 virtual Error
962 SetOptionValue (CommandInterpreter &interpreter,
963 uint32_t option_idx,
964 const char *option_arg)
965 {
966 Error error;
967 const int short_option = g_memory_find_option_table[option_idx].short_option;
968
969 switch (short_option)
970 {
971 case 'e':
972 m_expr.SetValueFromCString(option_arg);
973 break;
974
975 case 's':
976 m_string.SetValueFromCString(option_arg);
977 break;
978
979 case 'c':
980 if (m_count.SetValueFromCString(option_arg).Fail())
981 error.SetErrorString("unrecognized value for count");
982 break;
983
984
985 case 'r':
986 m_do_read.SetValueFromCString("true");
987 break;
988
989 default:
990 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
991 break;
992 }
993 return error;
994 }
995
996 virtual void
997 OptionParsingStarting (CommandInterpreter &interpreter)
998 {
999 m_expr.Clear();
1000 m_string.Clear();
1001 m_count.Clear();
1002 m_do_read.Clear();
1003 }
1004
1005 OptionValueString m_expr;
1006 OptionValueString m_string;
1007 OptionValueUInt64 m_count;
1008 OptionValueBoolean m_do_read;
1009 };
1010
1011 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1012 CommandObjectParsed (interpreter,
1013 "memory find",
1014 "Find a value in the memory of the process being debugged.",
1015 NULL,
1016 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
1017 m_option_group (interpreter),
1018 m_memory_options ()
1019 {
1020 CommandArgumentEntry arg1;
1021 CommandArgumentEntry arg2;
1022 CommandArgumentData addr_arg;
1023 CommandArgumentData value_arg;
1024
1025 // Define the first (and only) variant of this arg.
1026 addr_arg.arg_type = eArgTypeAddress;
1027 addr_arg.arg_repetition = eArgRepeatPlain;
1028
1029 // There is only one variant this argument could be; put it into the argument entry.
1030 arg1.push_back (addr_arg);
1031
1032 // Define the first (and only) variant of this arg.
1033 value_arg.arg_type = eArgTypeValue;
1034 value_arg.arg_repetition = eArgRepeatPlus;
1035
1036 // There is only one variant this argument could be; put it into the argument entry.
1037 arg2.push_back (value_arg);
1038
1039 // Push the data for the first argument into the m_arguments vector.
1040 m_arguments.push_back (arg1);
1041 m_arguments.push_back (arg2);
1042
1043 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1044 m_option_group.Finalize();
1045 }
1046
1047 virtual
1048 ~CommandObjectMemoryFind ()
1049 {
1050 }
1051
1052 Options *
1053 GetOptions ()
1054 {
1055 return &m_option_group;
1056 }
1057
1058protected:
1059 virtual bool
1060 DoExecute (Args& command, CommandReturnObject &result)
1061 {
1062 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1063 Process *process = m_exe_ctx.GetProcessPtr();
1064
1065 const size_t argc = command.GetArgumentCount();
1066
1067 if (argc != 2)
1068 {
1069 result.AppendError("Two addressed needed for memory find");
1070 return false;
1071 }
1072
1073 Error error;
1074 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1075 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1076 {
1077 result.AppendError("invalid low address");
1078 return false;
1079 }
1080 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1081 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1082 {
1083 result.AppendError("invalid low address");
1084 return false;
1085 }
1086
1087 if (high_addr <= low_addr)
1088 {
1089 result.AppendError("starting address must be smaller than ending address");
1090 return false;
1091 }
1092
1093 lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1094
1095 DataBufferHeap buffer;
1096
1097 if (m_memory_options.m_string.OptionWasSet())
1098 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1099 else if (m_memory_options.m_expr.OptionWasSet())
1100 {
1101 StackFrame* frame = m_exe_ctx.GetFramePtr();
1102 ValueObjectSP result_sp;
1103 if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
1104 {
1105 uint64_t value = result_sp->GetValueAsUnsigned(0);
1106 switch (result_sp->GetClangType().GetByteSize())
1107 {
1108 case 1: {
1109 uint8_t byte = (uint8_t)value;
1110 buffer.CopyData(&byte,1);
1111 }
1112 break;
1113 case 2: {
1114 uint16_t word = (uint16_t)value;
1115 buffer.CopyData(&word,2);
1116 }
1117 break;
1118 case 4: {
1119 uint32_t lword = (uint32_t)value;
1120 buffer.CopyData(&lword,4);
1121 }
1122 break;
1123 case 8: {
1124 buffer.CopyData(&value, 8);
1125 }
1126 break;
1127 case 3:
1128 case 5:
1129 case 6:
1130 case 7:
1131 result.AppendError("unknown type. pass a string instead");
1132 return false;
1133 default:
1134 result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
1135 return false;
1136 }
1137 }
1138 else
1139 {
1140 result.AppendError("expression evaluation failed. pass a string instead?");
1141 return false;
1142 }
1143 }
1144 else
1145 {
1146 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1147 return false;
1148 }
1149
1150 size_t count = m_memory_options.m_count.GetCurrentValue();
1151 found_location = low_addr;
1152 bool ever_found = false;
1153 while (count)
1154 {
1155 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1156 if (found_location == LLDB_INVALID_ADDRESS)
1157 {
1158 if (!ever_found)
1159 {
1160 result.AppendMessage("Your data was not found within the range.\n");
1161 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1162 }
1163 else
1164 result.AppendMessage("No more matches found within the range.\n");
1165 break;
1166 }
1167 result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
1168 if (m_memory_options.m_do_read.GetCurrentValue())
1169 {
1170 StreamString cmd_buffer;
1171 cmd_buffer.Printf("memory read 0x%" PRIx64, found_location);
1172 m_interpreter.HandleCommand(cmd_buffer.GetData(), eLazyBoolNo, result);
1173 }
1174 --count;
1175 found_location++;
1176 ever_found = true;
1177 }
1178
1179 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1180 return true;
1181 }
1182
1183 lldb::addr_t
1184 Search (lldb::addr_t low,
1185 lldb::addr_t high,
1186 uint8_t* buffer,
1187 size_t buffer_size)
1188 {
1189 Process *process = m_exe_ctx.GetProcessPtr();
1190 DataBufferHeap heap(buffer_size, 0);
1191 lldb::addr_t fictional_ptr = low;
1192 for (auto ptr = low;
1193 low < high;
1194 fictional_ptr++)
1195 {
1196 Error error;
1197 if (ptr == low || buffer_size == 1)
1198 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1199 else
1200 {
1201 memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
1202 process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
1203 }
1204 if (error.Fail())
1205 return LLDB_INVALID_ADDRESS;
1206 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1207 return fictional_ptr;
1208 if (ptr == low)
1209 ptr += buffer_size;
1210 else
1211 ptr += 1;
1212 }
1213 return LLDB_INVALID_ADDRESS;
1214 }
1215
1216 OptionGroupOptions m_option_group;
1217 OptionGroupFindMemory m_memory_options;
1218};
1219
Greg Clayton1deb7962011-10-25 06:44:01 +00001220
1221OptionDefinition
1222g_memory_write_option_table[] =
1223{
Virgile Belloe2607b52013-09-05 16:42:23 +00001224{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1225{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
Greg Clayton1deb7962011-10-25 06:44:01 +00001226};
1227
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001228//----------------------------------------------------------------------
1229// Write memory to the inferior process
1230//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001231class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001232{
1233public:
1234
Greg Clayton1deb7962011-10-25 06:44:01 +00001235 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001236 {
1237 public:
Greg Clayton1deb7962011-10-25 06:44:01 +00001238 OptionGroupWriteMemory () :
1239 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001240 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001241 }
1242
1243 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +00001244 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001245 {
1246 }
1247
Greg Clayton1deb7962011-10-25 06:44:01 +00001248 virtual uint32_t
1249 GetNumDefinitions ()
1250 {
1251 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1252 }
Enrico Granata53468432013-11-13 02:18:44 +00001253
Greg Clayton1deb7962011-10-25 06:44:01 +00001254 virtual const OptionDefinition*
1255 GetDefinitions ()
1256 {
1257 return g_memory_write_option_table;
1258 }
Enrico Granata53468432013-11-13 02:18:44 +00001259
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001260 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +00001261 SetOptionValue (CommandInterpreter &interpreter,
1262 uint32_t option_idx,
1263 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001264 {
1265 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001266 const int short_option = g_memory_write_option_table[option_idx].short_option;
Enrico Granata53468432013-11-13 02:18:44 +00001267
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001268 switch (short_option)
1269 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001270 case 'i':
1271 m_infile.SetFile (option_arg, true);
1272 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001273 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001274 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +00001275 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001276 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001277 break;
Enrico Granata53468432013-11-13 02:18:44 +00001278
Greg Clayton1deb7962011-10-25 06:44:01 +00001279 case 'o':
1280 {
1281 bool success;
1282 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
1283 if (!success)
1284 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001285 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +00001286 }
1287 }
1288 break;
1289
1290 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001291 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +00001292 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001293 }
1294 return error;
1295 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001296
1297 virtual void
1298 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001299 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001300 m_infile.Clear();
1301 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001302 }
1303
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001304 FileSpec m_infile;
1305 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001306 };
1307
Greg Claytona7015092010-09-18 01:14:36 +00001308 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001309 CommandObjectParsed (interpreter,
1310 "memory write",
1311 "Write to the memory of the process being debugged.",
1312 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +00001313 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001314 m_option_group (interpreter),
1315 m_format_options (eFormatBytes, 1, UINT64_MAX),
1316 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001317 {
Caroline Tice405fe672010-10-04 22:28:36 +00001318 CommandArgumentEntry arg1;
1319 CommandArgumentEntry arg2;
1320 CommandArgumentData addr_arg;
1321 CommandArgumentData value_arg;
1322
1323 // Define the first (and only) variant of this arg.
1324 addr_arg.arg_type = eArgTypeAddress;
1325 addr_arg.arg_repetition = eArgRepeatPlain;
1326
1327 // There is only one variant this argument could be; put it into the argument entry.
1328 arg1.push_back (addr_arg);
1329
1330 // Define the first (and only) variant of this arg.
1331 value_arg.arg_type = eArgTypeValue;
1332 value_arg.arg_repetition = eArgRepeatPlus;
1333
1334 // There is only one variant this argument could be; put it into the argument entry.
1335 arg2.push_back (value_arg);
1336
1337 // Push the data for the first argument into the m_arguments vector.
1338 m_arguments.push_back (arg1);
1339 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001340
1341 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1342 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1343 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1344 m_option_group.Finalize();
1345
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001346 }
1347
1348 virtual
1349 ~CommandObjectMemoryWrite ()
1350 {
1351 }
1352
1353 Options *
1354 GetOptions ()
1355 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001356 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001357 }
1358
1359 bool
1360 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1361 {
1362 if (total_byte_size > 8)
1363 return false;
1364
1365 if (total_byte_size == 8)
1366 return true;
1367
1368 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1369 return uval64 <= max;
1370 }
1371
1372 bool
1373 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1374 {
1375 if (total_byte_size > 8)
1376 return false;
1377
1378 if (total_byte_size == 8)
1379 return true;
1380
1381 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1382 const int64_t min = ~(max);
1383 return min <= sval64 && sval64 <= max;
1384 }
1385
Jim Ingham5a988412012-06-08 21:56:10 +00001386protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001387 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001388 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001389 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001390 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1391 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001392
1393 const size_t argc = command.GetArgumentCount();
1394
Greg Clayton1deb7962011-10-25 06:44:01 +00001395 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001396 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001397 if (argc < 1)
1398 {
1399 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1400 result.SetStatus(eReturnStatusFailed);
1401 return false;
1402 }
1403 }
1404 else if (argc < 2)
1405 {
1406 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 +00001407 result.SetStatus(eReturnStatusFailed);
1408 return false;
1409 }
1410
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001411 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001412 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1413 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001414
Greg Clayton1deb7962011-10-25 06:44:01 +00001415 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1416 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001417
Greg Claytonb9d5df52012-12-06 22:49:16 +00001418 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001419 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001420 command.GetArgumentAtIndex(0),
1421 LLDB_INVALID_ADDRESS,
1422 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001423
1424 if (addr == LLDB_INVALID_ADDRESS)
1425 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001426 result.AppendError("invalid address expression\n");
1427 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001428 result.SetStatus(eReturnStatusFailed);
1429 return false;
1430 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001431
Greg Clayton1deb7962011-10-25 06:44:01 +00001432 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001433 {
1434 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +00001435 if (item_byte_size > 0)
1436 length = item_byte_size;
1437 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001438 if (data_sp)
1439 {
1440 length = data_sp->GetByteSize();
1441 if (length > 0)
1442 {
1443 Error error;
1444 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1445
1446 if (bytes_written == length)
1447 {
1448 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001449 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001450 result.SetStatus(eReturnStatusSuccessFinishResult);
1451 }
1452 else if (bytes_written > 0)
1453 {
1454 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001455 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 +00001456 result.SetStatus(eReturnStatusSuccessFinishResult);
1457 }
1458 else
1459 {
Daniel Malead01b2952012-11-29 21:49:15 +00001460 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001461 result.SetStatus(eReturnStatusFailed);
1462 }
1463 }
1464 }
1465 else
1466 {
1467 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1468 result.SetStatus(eReturnStatusFailed);
1469 }
1470 return result.Succeeded();
1471 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001472 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001473 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001474 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001475 item_byte_size = buffer.GetAddressByteSize();
1476 else
1477 item_byte_size = 1;
1478 }
1479
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001480 command.Shift(); // shift off the address argument
1481 uint64_t uval64;
1482 int64_t sval64;
1483 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001484 const size_t num_value_args = command.GetArgumentCount();
1485 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001486 {
1487 const char *value_str = command.GetArgumentAtIndex(i);
1488
Greg Clayton1deb7962011-10-25 06:44:01 +00001489 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001490 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001491 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001492 case eFormatFloat: // TODO: add support for floats soon
1493 case eFormatCharPrintable:
1494 case eFormatBytesWithASCII:
1495 case eFormatComplex:
1496 case eFormatEnum:
1497 case eFormatUnicode16:
1498 case eFormatUnicode32:
1499 case eFormatVectorOfChar:
1500 case eFormatVectorOfSInt8:
1501 case eFormatVectorOfUInt8:
1502 case eFormatVectorOfSInt16:
1503 case eFormatVectorOfUInt16:
1504 case eFormatVectorOfSInt32:
1505 case eFormatVectorOfUInt32:
1506 case eFormatVectorOfSInt64:
1507 case eFormatVectorOfUInt64:
1508 case eFormatVectorOfFloat32:
1509 case eFormatVectorOfFloat64:
1510 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001511 case eFormatOSType:
1512 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001513 case eFormatAddressInfo:
1514 case eFormatHexFloat:
1515 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001516 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001517 result.AppendError("unsupported format for writing memory");
1518 result.SetStatus(eReturnStatusFailed);
1519 return false;
1520
1521 case eFormatDefault:
1522 case eFormatBytes:
1523 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001524 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001525 case eFormatPointer:
1526
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001527 // Decode hex bytes
1528 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1529 if (!success)
1530 {
1531 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1532 result.SetStatus(eReturnStatusFailed);
1533 return false;
1534 }
1535 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1536 {
Sylvestre Ledru779f9212013-10-31 23:55:19 +00001537 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001538 result.SetStatus(eReturnStatusFailed);
1539 return false;
1540 }
1541 buffer.PutMaxHex64 (uval64, item_byte_size);
1542 break;
1543
1544 case eFormatBoolean:
1545 uval64 = Args::StringToBoolean(value_str, false, &success);
1546 if (!success)
1547 {
1548 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1549 result.SetStatus(eReturnStatusFailed);
1550 return false;
1551 }
1552 buffer.PutMaxHex64 (uval64, item_byte_size);
1553 break;
1554
1555 case eFormatBinary:
1556 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1557 if (!success)
1558 {
1559 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1560 result.SetStatus(eReturnStatusFailed);
1561 return false;
1562 }
1563 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1564 {
Sylvestre Ledru779f9212013-10-31 23:55:19 +00001565 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001566 result.SetStatus(eReturnStatusFailed);
1567 return false;
1568 }
1569 buffer.PutMaxHex64 (uval64, item_byte_size);
1570 break;
1571
Greg Clayton4e4294b2011-06-17 23:50:44 +00001572 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001573 case eFormatChar:
1574 case eFormatCString:
1575 if (value_str[0])
1576 {
1577 size_t len = strlen (value_str);
1578 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001579 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001580 ++len;
1581 Error error;
1582 if (process->WriteMemory (addr, value_str, len, error) == len)
1583 {
1584 addr += len;
1585 }
1586 else
1587 {
Daniel Malead01b2952012-11-29 21:49:15 +00001588 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001589 result.SetStatus(eReturnStatusFailed);
1590 return false;
1591 }
1592 }
1593 break;
1594
1595 case eFormatDecimal:
1596 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1597 if (!success)
1598 {
1599 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1600 result.SetStatus(eReturnStatusFailed);
1601 return false;
1602 }
1603 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1604 {
Sylvestre Ledru779f9212013-10-31 23:55:19 +00001605 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %zu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001606 result.SetStatus(eReturnStatusFailed);
1607 return false;
1608 }
1609 buffer.PutMaxHex64 (sval64, item_byte_size);
1610 break;
1611
1612 case eFormatUnsigned:
1613 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1614 if (!success)
1615 {
1616 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1617 result.SetStatus(eReturnStatusFailed);
1618 return false;
1619 }
1620 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1621 {
Sylvestre Ledru779f9212013-10-31 23:55:19 +00001622 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001623 result.SetStatus(eReturnStatusFailed);
1624 return false;
1625 }
1626 buffer.PutMaxHex64 (uval64, item_byte_size);
1627 break;
1628
1629 case eFormatOctal:
1630 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1631 if (!success)
1632 {
1633 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1634 result.SetStatus(eReturnStatusFailed);
1635 return false;
1636 }
1637 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1638 {
Sylvestre Ledru779f9212013-10-31 23:55:19 +00001639 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001640 result.SetStatus(eReturnStatusFailed);
1641 return false;
1642 }
1643 buffer.PutMaxHex64 (uval64, item_byte_size);
1644 break;
1645 }
1646 }
1647
1648 if (!buffer.GetString().empty())
1649 {
1650 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001651 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001652 return true;
1653 else
1654 {
Daniel Malead01b2952012-11-29 21:49:15 +00001655 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001656 result.SetStatus(eReturnStatusFailed);
1657 return false;
1658 }
1659 }
1660 return true;
1661 }
1662
Greg Clayton1deb7962011-10-25 06:44:01 +00001663 OptionGroupOptions m_option_group;
1664 OptionGroupFormat m_format_options;
1665 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001666};
1667
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001668
1669//-------------------------------------------------------------------------
1670// CommandObjectMemory
1671//-------------------------------------------------------------------------
1672
Greg Clayton66111032010-06-23 01:19:29 +00001673CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001674 CommandObjectMultiword (interpreter,
1675 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001676 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001677 "memory <subcommand> [<subcommand-options>]")
1678{
Enrico Granata53468432013-11-13 02:18:44 +00001679 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001680 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1681 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001682}
1683
1684CommandObjectMemory::~CommandObjectMemory ()
1685{
1686}