blob: 58c0bfcdccb029842c7dc692782bab0923f52dea [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 {
Greg Clayton6fea17e2014-03-03 19:15:20 +0000654 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)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)
Greg Clayton6fea17e2014-03-03 19:15:20 +0000711 result.AppendWarningWithFormat("Not all bytes (%" PRIu64 "/%" PRIu64 ") were able to be read from 0x%" PRIx64 ".\n", (uint64_t)bytes_read, (uint64_t)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
Greg Clayton6fea17e2014-03-03 19:15:20 +0000881 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
Enrico Granata0947a6e2013-10-29 23:04:29 +0000882 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{
Enrico Granata6e49c482013-11-13 02:22:24 +0000920 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
Enrico Granata8d81a842013-11-13 20:08:30 +0000921 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
922 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many times to perform the search."},
923 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
Enrico Granata53468432013-11-13 02:18:44 +0000924};
925
Enrico Granata53468432013-11-13 02:18:44 +0000926//----------------------------------------------------------------------
927// Find the specified data in memory
928//----------------------------------------------------------------------
929class CommandObjectMemoryFind : public CommandObjectParsed
930{
931public:
932
933 class OptionGroupFindMemory : public OptionGroup
934 {
935 public:
936 OptionGroupFindMemory () :
937 OptionGroup(),
938 m_count(1),
Enrico Granata8d81a842013-11-13 20:08:30 +0000939 m_offset(0)
Enrico Granata53468432013-11-13 02:18:44 +0000940 {
941 }
942
943 virtual
944 ~OptionGroupFindMemory ()
945 {
946 }
947
948 virtual uint32_t
949 GetNumDefinitions ()
950 {
951 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
952 }
953
954 virtual const OptionDefinition*
955 GetDefinitions ()
956 {
957 return g_memory_find_option_table;
958 }
959
960 virtual Error
961 SetOptionValue (CommandInterpreter &interpreter,
962 uint32_t option_idx,
963 const char *option_arg)
964 {
965 Error error;
966 const int short_option = g_memory_find_option_table[option_idx].short_option;
967
968 switch (short_option)
969 {
970 case 'e':
971 m_expr.SetValueFromCString(option_arg);
972 break;
973
974 case 's':
975 m_string.SetValueFromCString(option_arg);
976 break;
977
978 case 'c':
979 if (m_count.SetValueFromCString(option_arg).Fail())
980 error.SetErrorString("unrecognized value for count");
981 break;
982
Enrico Granata8d81a842013-11-13 20:08:30 +0000983 case 'o':
984 if (m_offset.SetValueFromCString(option_arg).Fail())
985 error.SetErrorString("unrecognized value for dump-offset");
986 break;
987
Enrico Granata53468432013-11-13 02:18:44 +0000988 default:
989 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
990 break;
991 }
992 return error;
993 }
994
995 virtual void
996 OptionParsingStarting (CommandInterpreter &interpreter)
997 {
998 m_expr.Clear();
999 m_string.Clear();
1000 m_count.Clear();
Enrico Granata53468432013-11-13 02:18:44 +00001001 }
1002
1003 OptionValueString m_expr;
1004 OptionValueString m_string;
1005 OptionValueUInt64 m_count;
Enrico Granata8d81a842013-11-13 20:08:30 +00001006 OptionValueUInt64 m_offset;
Enrico Granata53468432013-11-13 02:18:44 +00001007 };
1008
1009 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1010 CommandObjectParsed (interpreter,
1011 "memory find",
1012 "Find a value in the memory of the process being debugged.",
1013 NULL,
1014 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
1015 m_option_group (interpreter),
1016 m_memory_options ()
1017 {
1018 CommandArgumentEntry arg1;
1019 CommandArgumentEntry arg2;
1020 CommandArgumentData addr_arg;
1021 CommandArgumentData value_arg;
1022
1023 // Define the first (and only) variant of this arg.
1024 addr_arg.arg_type = eArgTypeAddress;
1025 addr_arg.arg_repetition = eArgRepeatPlain;
1026
1027 // There is only one variant this argument could be; put it into the argument entry.
1028 arg1.push_back (addr_arg);
1029
1030 // Define the first (and only) variant of this arg.
1031 value_arg.arg_type = eArgTypeValue;
1032 value_arg.arg_repetition = eArgRepeatPlus;
1033
1034 // There is only one variant this argument could be; put it into the argument entry.
1035 arg2.push_back (value_arg);
1036
1037 // Push the data for the first argument into the m_arguments vector.
1038 m_arguments.push_back (arg1);
1039 m_arguments.push_back (arg2);
1040
1041 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1042 m_option_group.Finalize();
1043 }
1044
1045 virtual
1046 ~CommandObjectMemoryFind ()
1047 {
1048 }
1049
1050 Options *
1051 GetOptions ()
1052 {
1053 return &m_option_group;
1054 }
1055
1056protected:
1057 virtual bool
1058 DoExecute (Args& command, CommandReturnObject &result)
1059 {
1060 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1061 Process *process = m_exe_ctx.GetProcessPtr();
1062
1063 const size_t argc = command.GetArgumentCount();
1064
1065 if (argc != 2)
1066 {
Enrico Granata6e49c482013-11-13 02:22:24 +00001067 result.AppendError("two addresses needed for memory find");
Enrico Granata53468432013-11-13 02:18:44 +00001068 return false;
1069 }
1070
1071 Error error;
1072 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1073 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1074 {
1075 result.AppendError("invalid low address");
1076 return false;
1077 }
1078 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1079 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1080 {
1081 result.AppendError("invalid low address");
1082 return false;
1083 }
1084
1085 if (high_addr <= low_addr)
1086 {
1087 result.AppendError("starting address must be smaller than ending address");
1088 return false;
1089 }
1090
1091 lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1092
1093 DataBufferHeap buffer;
1094
1095 if (m_memory_options.m_string.OptionWasSet())
1096 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1097 else if (m_memory_options.m_expr.OptionWasSet())
1098 {
1099 StackFrame* frame = m_exe_ctx.GetFramePtr();
1100 ValueObjectSP result_sp;
1101 if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
1102 {
1103 uint64_t value = result_sp->GetValueAsUnsigned(0);
1104 switch (result_sp->GetClangType().GetByteSize())
1105 {
1106 case 1: {
1107 uint8_t byte = (uint8_t)value;
1108 buffer.CopyData(&byte,1);
1109 }
1110 break;
1111 case 2: {
1112 uint16_t word = (uint16_t)value;
1113 buffer.CopyData(&word,2);
1114 }
1115 break;
1116 case 4: {
1117 uint32_t lword = (uint32_t)value;
1118 buffer.CopyData(&lword,4);
1119 }
1120 break;
1121 case 8: {
1122 buffer.CopyData(&value, 8);
1123 }
1124 break;
1125 case 3:
1126 case 5:
1127 case 6:
1128 case 7:
1129 result.AppendError("unknown type. pass a string instead");
1130 return false;
1131 default:
1132 result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
1133 return false;
1134 }
1135 }
1136 else
1137 {
1138 result.AppendError("expression evaluation failed. pass a string instead?");
1139 return false;
1140 }
1141 }
1142 else
1143 {
1144 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1145 return false;
1146 }
1147
1148 size_t count = m_memory_options.m_count.GetCurrentValue();
1149 found_location = low_addr;
1150 bool ever_found = false;
1151 while (count)
1152 {
1153 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1154 if (found_location == LLDB_INVALID_ADDRESS)
1155 {
1156 if (!ever_found)
1157 {
1158 result.AppendMessage("Your data was not found within the range.\n");
1159 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1160 }
1161 else
1162 result.AppendMessage("No more matches found within the range.\n");
1163 break;
1164 }
1165 result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
Enrico Granata8d81a842013-11-13 20:08:30 +00001166
1167 DataBufferHeap dumpbuffer(32,0);
1168 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1169 if (!error.Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001170 {
Enrico Granata8d81a842013-11-13 20:08:30 +00001171 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1172 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1173 result.GetOutputStream().EOL();
Enrico Granata53468432013-11-13 02:18:44 +00001174 }
Enrico Granata8d81a842013-11-13 20:08:30 +00001175
Enrico Granata53468432013-11-13 02:18:44 +00001176 --count;
1177 found_location++;
1178 ever_found = true;
1179 }
1180
1181 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1182 return true;
1183 }
1184
1185 lldb::addr_t
1186 Search (lldb::addr_t low,
1187 lldb::addr_t high,
1188 uint8_t* buffer,
1189 size_t buffer_size)
1190 {
1191 Process *process = m_exe_ctx.GetProcessPtr();
1192 DataBufferHeap heap(buffer_size, 0);
1193 lldb::addr_t fictional_ptr = low;
1194 for (auto ptr = low;
1195 low < high;
1196 fictional_ptr++)
1197 {
1198 Error error;
1199 if (ptr == low || buffer_size == 1)
1200 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1201 else
1202 {
1203 memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
1204 process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
1205 }
1206 if (error.Fail())
1207 return LLDB_INVALID_ADDRESS;
1208 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1209 return fictional_ptr;
1210 if (ptr == low)
1211 ptr += buffer_size;
1212 else
1213 ptr += 1;
1214 }
1215 return LLDB_INVALID_ADDRESS;
1216 }
1217
1218 OptionGroupOptions m_option_group;
1219 OptionGroupFindMemory m_memory_options;
1220};
1221
Greg Clayton1deb7962011-10-25 06:44:01 +00001222
1223OptionDefinition
1224g_memory_write_option_table[] =
1225{
Virgile Belloe2607b52013-09-05 16:42:23 +00001226{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1227{ 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 +00001228};
1229
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001230//----------------------------------------------------------------------
1231// Write memory to the inferior process
1232//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001233class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001234{
1235public:
1236
Greg Clayton1deb7962011-10-25 06:44:01 +00001237 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001238 {
1239 public:
Greg Clayton1deb7962011-10-25 06:44:01 +00001240 OptionGroupWriteMemory () :
1241 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001242 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001243 }
1244
1245 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +00001246 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001247 {
1248 }
1249
Greg Clayton1deb7962011-10-25 06:44:01 +00001250 virtual uint32_t
1251 GetNumDefinitions ()
1252 {
1253 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1254 }
Enrico Granata53468432013-11-13 02:18:44 +00001255
Greg Clayton1deb7962011-10-25 06:44:01 +00001256 virtual const OptionDefinition*
1257 GetDefinitions ()
1258 {
1259 return g_memory_write_option_table;
1260 }
Enrico Granata53468432013-11-13 02:18:44 +00001261
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001262 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +00001263 SetOptionValue (CommandInterpreter &interpreter,
1264 uint32_t option_idx,
1265 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001266 {
1267 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001268 const int short_option = g_memory_write_option_table[option_idx].short_option;
Enrico Granata53468432013-11-13 02:18:44 +00001269
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001270 switch (short_option)
1271 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001272 case 'i':
1273 m_infile.SetFile (option_arg, true);
1274 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001275 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001276 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +00001277 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001278 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001279 break;
Enrico Granata53468432013-11-13 02:18:44 +00001280
Greg Clayton1deb7962011-10-25 06:44:01 +00001281 case 'o':
1282 {
1283 bool success;
1284 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
1285 if (!success)
1286 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001287 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +00001288 }
1289 }
1290 break;
1291
1292 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001293 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +00001294 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001295 }
1296 return error;
1297 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001298
1299 virtual void
1300 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001301 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001302 m_infile.Clear();
1303 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001304 }
1305
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001306 FileSpec m_infile;
1307 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001308 };
1309
Greg Claytona7015092010-09-18 01:14:36 +00001310 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001311 CommandObjectParsed (interpreter,
1312 "memory write",
1313 "Write to the memory of the process being debugged.",
1314 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +00001315 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001316 m_option_group (interpreter),
1317 m_format_options (eFormatBytes, 1, UINT64_MAX),
1318 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001319 {
Caroline Tice405fe672010-10-04 22:28:36 +00001320 CommandArgumentEntry arg1;
1321 CommandArgumentEntry arg2;
1322 CommandArgumentData addr_arg;
1323 CommandArgumentData value_arg;
1324
1325 // Define the first (and only) variant of this arg.
1326 addr_arg.arg_type = eArgTypeAddress;
1327 addr_arg.arg_repetition = eArgRepeatPlain;
1328
1329 // There is only one variant this argument could be; put it into the argument entry.
1330 arg1.push_back (addr_arg);
1331
1332 // Define the first (and only) variant of this arg.
1333 value_arg.arg_type = eArgTypeValue;
1334 value_arg.arg_repetition = eArgRepeatPlus;
1335
1336 // There is only one variant this argument could be; put it into the argument entry.
1337 arg2.push_back (value_arg);
1338
1339 // Push the data for the first argument into the m_arguments vector.
1340 m_arguments.push_back (arg1);
1341 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001342
1343 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1344 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1345 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1346 m_option_group.Finalize();
1347
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001348 }
1349
1350 virtual
1351 ~CommandObjectMemoryWrite ()
1352 {
1353 }
1354
1355 Options *
1356 GetOptions ()
1357 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001358 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001359 }
1360
1361 bool
1362 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1363 {
1364 if (total_byte_size > 8)
1365 return false;
1366
1367 if (total_byte_size == 8)
1368 return true;
1369
1370 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1371 return uval64 <= max;
1372 }
1373
1374 bool
1375 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1376 {
1377 if (total_byte_size > 8)
1378 return false;
1379
1380 if (total_byte_size == 8)
1381 return true;
1382
1383 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1384 const int64_t min = ~(max);
1385 return min <= sval64 && sval64 <= max;
1386 }
1387
Jim Ingham5a988412012-06-08 21:56:10 +00001388protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001389 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001390 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001391 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001392 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1393 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001394
1395 const size_t argc = command.GetArgumentCount();
1396
Greg Clayton1deb7962011-10-25 06:44:01 +00001397 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001398 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001399 if (argc < 1)
1400 {
1401 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1402 result.SetStatus(eReturnStatusFailed);
1403 return false;
1404 }
1405 }
1406 else if (argc < 2)
1407 {
1408 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 +00001409 result.SetStatus(eReturnStatusFailed);
1410 return false;
1411 }
1412
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001413 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001414 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1415 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001416
Greg Clayton1deb7962011-10-25 06:44:01 +00001417 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1418 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001419
Greg Claytonb9d5df52012-12-06 22:49:16 +00001420 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001421 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001422 command.GetArgumentAtIndex(0),
1423 LLDB_INVALID_ADDRESS,
1424 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001425
1426 if (addr == LLDB_INVALID_ADDRESS)
1427 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001428 result.AppendError("invalid address expression\n");
1429 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001430 result.SetStatus(eReturnStatusFailed);
1431 return false;
1432 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001433
Greg Clayton1deb7962011-10-25 06:44:01 +00001434 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001435 {
1436 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +00001437 if (item_byte_size > 0)
1438 length = item_byte_size;
1439 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001440 if (data_sp)
1441 {
1442 length = data_sp->GetByteSize();
1443 if (length > 0)
1444 {
1445 Error error;
1446 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1447
1448 if (bytes_written == length)
1449 {
1450 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001451 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001452 result.SetStatus(eReturnStatusSuccessFinishResult);
1453 }
1454 else if (bytes_written > 0)
1455 {
1456 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001457 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 +00001458 result.SetStatus(eReturnStatusSuccessFinishResult);
1459 }
1460 else
1461 {
Daniel Malead01b2952012-11-29 21:49:15 +00001462 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001463 result.SetStatus(eReturnStatusFailed);
1464 }
1465 }
1466 }
1467 else
1468 {
1469 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1470 result.SetStatus(eReturnStatusFailed);
1471 }
1472 return result.Succeeded();
1473 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001474 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001475 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001476 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001477 item_byte_size = buffer.GetAddressByteSize();
1478 else
1479 item_byte_size = 1;
1480 }
1481
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001482 command.Shift(); // shift off the address argument
1483 uint64_t uval64;
1484 int64_t sval64;
1485 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001486 const size_t num_value_args = command.GetArgumentCount();
1487 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001488 {
1489 const char *value_str = command.GetArgumentAtIndex(i);
1490
Greg Clayton1deb7962011-10-25 06:44:01 +00001491 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001492 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001493 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001494 case eFormatFloat: // TODO: add support for floats soon
1495 case eFormatCharPrintable:
1496 case eFormatBytesWithASCII:
1497 case eFormatComplex:
1498 case eFormatEnum:
1499 case eFormatUnicode16:
1500 case eFormatUnicode32:
1501 case eFormatVectorOfChar:
1502 case eFormatVectorOfSInt8:
1503 case eFormatVectorOfUInt8:
1504 case eFormatVectorOfSInt16:
1505 case eFormatVectorOfUInt16:
1506 case eFormatVectorOfSInt32:
1507 case eFormatVectorOfUInt32:
1508 case eFormatVectorOfSInt64:
1509 case eFormatVectorOfUInt64:
1510 case eFormatVectorOfFloat32:
1511 case eFormatVectorOfFloat64:
1512 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001513 case eFormatOSType:
1514 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001515 case eFormatAddressInfo:
1516 case eFormatHexFloat:
1517 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001518 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001519 result.AppendError("unsupported format for writing memory");
1520 result.SetStatus(eReturnStatusFailed);
1521 return false;
1522
1523 case eFormatDefault:
1524 case eFormatBytes:
1525 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001526 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001527 case eFormatPointer:
1528
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001529 // Decode hex bytes
1530 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1531 if (!success)
1532 {
1533 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1534 result.SetStatus(eReturnStatusFailed);
1535 return false;
1536 }
1537 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1538 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001539 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001540 result.SetStatus(eReturnStatusFailed);
1541 return false;
1542 }
1543 buffer.PutMaxHex64 (uval64, item_byte_size);
1544 break;
1545
1546 case eFormatBoolean:
1547 uval64 = Args::StringToBoolean(value_str, false, &success);
1548 if (!success)
1549 {
1550 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1551 result.SetStatus(eReturnStatusFailed);
1552 return false;
1553 }
1554 buffer.PutMaxHex64 (uval64, item_byte_size);
1555 break;
1556
1557 case eFormatBinary:
1558 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1559 if (!success)
1560 {
1561 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1562 result.SetStatus(eReturnStatusFailed);
1563 return false;
1564 }
1565 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1566 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001567 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001568 result.SetStatus(eReturnStatusFailed);
1569 return false;
1570 }
1571 buffer.PutMaxHex64 (uval64, item_byte_size);
1572 break;
1573
Greg Clayton4e4294b2011-06-17 23:50:44 +00001574 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001575 case eFormatChar:
1576 case eFormatCString:
1577 if (value_str[0])
1578 {
1579 size_t len = strlen (value_str);
1580 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001581 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001582 ++len;
1583 Error error;
1584 if (process->WriteMemory (addr, value_str, len, error) == len)
1585 {
1586 addr += len;
1587 }
1588 else
1589 {
Daniel Malead01b2952012-11-29 21:49:15 +00001590 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001591 result.SetStatus(eReturnStatusFailed);
1592 return false;
1593 }
1594 }
1595 break;
1596
1597 case eFormatDecimal:
1598 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1599 if (!success)
1600 {
1601 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1602 result.SetStatus(eReturnStatusFailed);
1603 return false;
1604 }
1605 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1606 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001607 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %" PRIu64 " byte signed integer value.\n", sval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001608 result.SetStatus(eReturnStatusFailed);
1609 return false;
1610 }
1611 buffer.PutMaxHex64 (sval64, item_byte_size);
1612 break;
1613
1614 case eFormatUnsigned:
1615 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1616 if (!success)
1617 {
1618 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1619 result.SetStatus(eReturnStatusFailed);
1620 return false;
1621 }
1622 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1623 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001624 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001625 result.SetStatus(eReturnStatusFailed);
1626 return false;
1627 }
1628 buffer.PutMaxHex64 (uval64, item_byte_size);
1629 break;
1630
1631 case eFormatOctal:
1632 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1633 if (!success)
1634 {
1635 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1636 result.SetStatus(eReturnStatusFailed);
1637 return false;
1638 }
1639 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1640 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001641 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001642 result.SetStatus(eReturnStatusFailed);
1643 return false;
1644 }
1645 buffer.PutMaxHex64 (uval64, item_byte_size);
1646 break;
1647 }
1648 }
1649
1650 if (!buffer.GetString().empty())
1651 {
1652 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001653 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001654 return true;
1655 else
1656 {
Daniel Malead01b2952012-11-29 21:49:15 +00001657 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001658 result.SetStatus(eReturnStatusFailed);
1659 return false;
1660 }
1661 }
1662 return true;
1663 }
1664
Greg Clayton1deb7962011-10-25 06:44:01 +00001665 OptionGroupOptions m_option_group;
1666 OptionGroupFormat m_format_options;
1667 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001668};
1669
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001670
1671//-------------------------------------------------------------------------
1672// CommandObjectMemory
1673//-------------------------------------------------------------------------
1674
Greg Clayton66111032010-06-23 01:19:29 +00001675CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001676 CommandObjectMultiword (interpreter,
1677 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001678 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001679 "memory <subcommand> [<subcommand-options>]")
1680{
Enrico Granata53468432013-11-13 02:18:44 +00001681 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001682 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1683 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001684}
1685
1686CommandObjectMemory::~CommandObjectMemory ()
1687{
1688}