blob: f8fe456d4d467e19044cd3c3373b582599fe8fd7 [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
10#include "CommandObjectMemory.h"
11
12// C Includes
Virgile Bellobdae3782013-08-28 12:14:27 +000013#include <inttypes.h>
14
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015// C++ Includes
16// Other libraries and framework includes
Zachary Turnera78bd7f2015-03-03 23:11:11 +000017#include "clang/AST/Decl.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include "lldb/Core/DataBufferHeap.h"
20#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000021#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000022#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000023#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000024#include "lldb/Core/ValueObjectMemory.h"
Enrico Granata4d93b8c2013-09-30 19:11:51 +000025#include "lldb/DataFormatters/ValueObjectPrinter.h"
Sean Callanan4dbb2712015-09-25 20:35:58 +000026#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000027#include "lldb/Host/StringConvert.h"
Greg Clayton66111032010-06-23 01:19:29 +000028#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000030#include "lldb/Interpreter/CommandInterpreter.h"
31#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000032#include "lldb/Interpreter/OptionGroupFormat.h"
33#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000034#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000035#include "lldb/Interpreter/OptionValueString.h"
Greg Claytond8d4a572015-08-11 21:38:15 +000036#include "lldb/Symbol/ClangASTContext.h"
Greg Clayton1f746072012-08-29 21:13:06 +000037#include "lldb/Symbol/TypeList.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000038#include "lldb/Target/MemoryHistory.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000039#include "lldb/Target/Process.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000040#include "lldb/Target/StackFrame.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000041#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042
43using namespace lldb;
44using namespace lldb_private;
45
Greg Clayton68ebae62011-04-28 20:55:26 +000046static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000047g_option_table[] =
48{
Zachary Turnerd37221d2014-07-09 16:31:49 +000049 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
50 { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, 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."},
51 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Enrico Granata40d35702015-11-04 02:12:09 +000052 { LLDB_OPT_SET_3, false , "offset" ,'E', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount ,"How many elements of the specified type to skip before starting to display data."},
Greg Clayton2346fcf2012-11-02 21:14:58 +000053 { LLDB_OPT_SET_1|
54 LLDB_OPT_SET_2|
Zachary Turnerd37221d2014-07-09 16:31:49 +000055 LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
Greg Clayton84c39662011-04-27 22:04:39 +000056};
57
58
59
60class OptionGroupReadMemory : public OptionGroup
61{
62public:
63
64 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000065 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000066 m_output_as_binary (false),
Enrico Granata7a336212015-10-29 23:40:24 +000067 m_view_as_type(),
68 m_offset(0,0)
Greg Clayton84c39662011-04-27 22:04:39 +000069 {
70 }
71
Bruce Mitchener13d21e92015-10-07 16:56:17 +000072 ~OptionGroupReadMemory () override
Greg Clayton84c39662011-04-27 22:04:39 +000073 {
74 }
75
76
Bruce Mitchener13d21e92015-10-07 16:56:17 +000077 uint32_t
78 GetNumDefinitions () override
Greg Clayton84c39662011-04-27 22:04:39 +000079 {
80 return sizeof (g_option_table) / sizeof (OptionDefinition);
81 }
82
Bruce Mitchener13d21e92015-10-07 16:56:17 +000083 const OptionDefinition*
84 GetDefinitions () override
Greg Clayton84c39662011-04-27 22:04:39 +000085 {
86 return g_option_table;
87 }
88
Bruce Mitchener13d21e92015-10-07 16:56:17 +000089 Error
Greg Clayton84c39662011-04-27 22:04:39 +000090 SetOptionValue (CommandInterpreter &interpreter,
91 uint32_t option_idx,
Bruce Mitchener13d21e92015-10-07 16:56:17 +000092 const char *option_arg) override
Greg Clayton84c39662011-04-27 22:04:39 +000093 {
94 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000095 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000096
97 switch (short_option)
98 {
99 case 'l':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000100 error = m_num_per_line.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000101 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +0000102 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000103 break;
Greg Clayton1deb7962011-10-25 06:44:01 +0000104
Greg Clayton84c39662011-04-27 22:04:39 +0000105 case 'b':
106 m_output_as_binary = true;
107 break;
108
109 case 't':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000110 error = m_view_as_type.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000111 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000112
113 case 'r':
114 m_force = true;
115 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000116
Tamas Berghammeraaaa1572015-11-04 19:32:01 +0000117 case 'E':
Enrico Granata7a336212015-10-29 23:40:24 +0000118 error = m_offset.SetValueFromString(option_arg);
119 break;
120
Greg Clayton84c39662011-04-27 22:04:39 +0000121 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000122 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000123 break;
124 }
125 return error;
126 }
127
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000128 void
129 OptionParsingStarting (CommandInterpreter &interpreter) override
Greg Clayton84c39662011-04-27 22:04:39 +0000130 {
Greg Clayton84c39662011-04-27 22:04:39 +0000131 m_num_per_line.Clear();
132 m_output_as_binary = false;
133 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000134 m_force = false;
Enrico Granata7a336212015-10-29 23:40:24 +0000135 m_offset.Clear();
Greg Clayton84c39662011-04-27 22:04:39 +0000136 }
137
Greg Clayton68ebae62011-04-28 20:55:26 +0000138 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000139 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000140 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000141 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000142 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
143 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000144 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000145 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000146 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000147
Greg Clayton68ebae62011-04-28 20:55:26 +0000148 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000149 {
150 default:
151 break;
152
153 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000154 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000155 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000156 if (!num_per_line_option_set)
157 m_num_per_line = 1;
158 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000159 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000160 break;
161
162 case eFormatCString:
163 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000164
165 case eFormatInstruction:
166 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000167 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000168 m_num_per_line = 1;
169 break;
170
171 case eFormatAddressInfo:
172 if (!byte_size_option_set)
173 byte_size_value = target->GetArchitecture().GetAddressByteSize();
174 m_num_per_line = 1;
175 if (!count_option_set)
176 format_options.GetCountValue() = 8;
177 break;
178
Greg Clayton84c39662011-04-27 22:04:39 +0000179 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000180 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000181 if (!num_per_line_option_set)
182 m_num_per_line = 4;
183 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000184 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000185 break;
186
187 case eFormatBinary:
188 case eFormatFloat:
189 case eFormatOctal:
190 case eFormatDecimal:
191 case eFormatEnum:
192 case eFormatUnicode16:
193 case eFormatUnicode32:
194 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000195 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000196 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000197 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000198 if (!num_per_line_option_set)
199 m_num_per_line = 1;
200 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000201 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000202 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000203
Greg Clayton84c39662011-04-27 22:04:39 +0000204 case eFormatBytes:
205 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000206 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000207 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000208 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000209 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000210 "\tconsider using a different display format or don't specify the byte size",
211 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000212 }
213 else
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 = 16;
217 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000218 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000219 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000220 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000221 case eFormatChar:
222 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000223 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000224 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000225 if (!num_per_line_option_set)
226 m_num_per_line = 32;
227 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000228 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000229 break;
230 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000231 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000232 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000233 if (!num_per_line_option_set)
234 m_num_per_line = 1;
235 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000236 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000237 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000238 case eFormatComplexInteger:
239 if (!byte_size_option_set)
240 byte_size_value = 8;
241 if (!num_per_line_option_set)
242 m_num_per_line = 1;
243 if (!count_option_set)
244 format_options.GetCountValue() = 8;
245 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000246 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000247 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000248 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000249 if (!num_per_line_option_set)
250 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000251 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000252 {
253 case 1:
254 case 2:
255 m_num_per_line = 8;
256 break;
257 case 4:
258 m_num_per_line = 4;
259 break;
260 case 8:
261 m_num_per_line = 2;
262 break;
263 default:
264 m_num_per_line = 1;
265 break;
266 }
267 }
268 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000269 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000270 break;
271
272 case eFormatVectorOfChar:
273 case eFormatVectorOfSInt8:
274 case eFormatVectorOfUInt8:
275 case eFormatVectorOfSInt16:
276 case eFormatVectorOfUInt16:
277 case eFormatVectorOfSInt32:
278 case eFormatVectorOfUInt32:
279 case eFormatVectorOfSInt64:
280 case eFormatVectorOfUInt64:
Ewan Crawforda0f08672015-10-16 08:28:47 +0000281 case eFormatVectorOfFloat16:
Greg Clayton84c39662011-04-27 22:04:39 +0000282 case eFormatVectorOfFloat32:
283 case eFormatVectorOfFloat64:
284 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000285 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000286 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000287 if (!num_per_line_option_set)
288 m_num_per_line = 1;
289 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000290 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000291 break;
292 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000293 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000294 }
295
Greg Clayton82f4cf42011-10-26 04:32:38 +0000296 bool
297 AnyOptionWasSet () const
298 {
299 return m_num_per_line.OptionWasSet() ||
300 m_output_as_binary ||
Enrico Granata7a336212015-10-29 23:40:24 +0000301 m_view_as_type.OptionWasSet() ||
302 m_offset.OptionWasSet();
Greg Clayton82f4cf42011-10-26 04:32:38 +0000303 }
304
Greg Clayton84c39662011-04-27 22:04:39 +0000305 OptionValueUInt64 m_num_per_line;
306 bool m_output_as_binary;
307 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000308 bool m_force;
Enrico Granata7a336212015-10-29 23:40:24 +0000309 OptionValueUInt64 m_offset;
Greg Clayton84c39662011-04-27 22:04:39 +0000310};
311
312
313
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000314//----------------------------------------------------------------------
315// Read memory from the inferior process
316//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000317class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000318{
319public:
320
Greg Claytona7015092010-09-18 01:14:36 +0000321 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000322 CommandObjectParsed (interpreter,
323 "memory read",
324 "Read from the memory of the process being debugged.",
325 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +0000326 eCommandRequiresTarget | eCommandProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000327 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000328 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000329 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000330 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000331 m_varobj_options(),
332 m_next_addr(LLDB_INVALID_ADDRESS),
333 m_prev_byte_size(0),
334 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
335 m_prev_memory_options (),
336 m_prev_outfile_options (),
337 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000338 {
Caroline Tice405fe672010-10-04 22:28:36 +0000339 CommandArgumentEntry arg1;
340 CommandArgumentEntry arg2;
341 CommandArgumentData start_addr_arg;
342 CommandArgumentData end_addr_arg;
343
344 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000345 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000346 start_addr_arg.arg_repetition = eArgRepeatPlain;
347
348 // There is only one variant this argument could be; put it into the argument entry.
349 arg1.push_back (start_addr_arg);
350
351 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000352 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000353 end_addr_arg.arg_repetition = eArgRepeatOptional;
354
355 // There is only one variant this argument could be; put it into the argument entry.
356 arg2.push_back (end_addr_arg);
357
358 // Push the data for the first argument into the m_arguments vector.
359 m_arguments.push_back (arg1);
360 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000361
Greg Clayton1deb7962011-10-25 06:44:01 +0000362 // Add the "--format" and "--count" options to group 1 and 3
363 m_option_group.Append (&m_format_options,
364 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000365 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000366 m_option_group.Append (&m_format_options,
367 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000368 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000369 // Add the "--size" option to group 1 and 2
370 m_option_group.Append (&m_format_options,
371 OptionGroupFormat::OPTION_GROUP_SIZE,
372 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000373 m_option_group.Append (&m_memory_options);
374 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 +0000375 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000376 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000377 }
378
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000379 ~CommandObjectMemoryRead () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 {
381 }
382
383 Options *
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000384 GetOptions () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385 {
Greg Clayton84c39662011-04-27 22:04:39 +0000386 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387 }
388
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000389 const char *
390 GetRepeatCommand (Args &current_command_args, uint32_t index) override
Greg Clayton82f4cf42011-10-26 04:32:38 +0000391 {
392 return m_cmd_name.c_str();
393 }
394
Jim Ingham5a988412012-06-08 21:56:10 +0000395protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000396 bool
397 DoExecute (Args& command, CommandReturnObject &result) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000398 {
Enrico Granatae87764f2015-05-27 05:04:35 +0000399 // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +0000400 Target *target = m_exe_ctx.GetTargetPtr();
401
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000402 const size_t argc = command.GetArgumentCount();
403
Greg Clayton82f4cf42011-10-26 04:32:38 +0000404 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000405 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000406 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 +0000407 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000408 result.SetStatus(eReturnStatusFailed);
409 return false;
410 }
411
Greg Claytona1e5dc82015-08-11 22:53:00 +0000412 CompilerType clang_ast_type;
Greg Clayton68ebae62011-04-28 20:55:26 +0000413 Error error;
414
Greg Clayton84c39662011-04-27 22:04:39 +0000415 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
416 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000417 {
Greg Clayton84c39662011-04-27 22:04:39 +0000418 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000419
Greg Clayton84c39662011-04-27 22:04:39 +0000420 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000421 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000422 TypeList type_list;
423 uint32_t reference_count = 0;
424 uint32_t pointer_count = 0;
425 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000426
427#define ALL_KEYWORDS \
428 KEYWORD("const") \
429 KEYWORD("volatile") \
430 KEYWORD("restrict") \
431 KEYWORD("struct") \
432 KEYWORD("class") \
433 KEYWORD("union")
434
435#define KEYWORD(s) s,
436 static const char *g_keywords[] =
437 {
438 ALL_KEYWORDS
439 };
440#undef KEYWORD
441
442#define KEYWORD(s) (sizeof(s) - 1),
443 static const int g_keyword_lengths[] =
444 {
445 ALL_KEYWORDS
446 };
447#undef KEYWORD
448
449#undef ALL_KEYWORDS
450
451 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000452 std::string type_str(view_as_type_cstr);
453
454 // Remove all instances of g_keywords that are followed by spaces
455 for (size_t i = 0; i < g_num_keywords; ++i)
456 {
457 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000458 int keyword_len = g_keyword_lengths[i];
459
460 idx = 0;
461 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000462 {
463 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000464 {
Greg Clayton84c39662011-04-27 22:04:39 +0000465 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000466 idx = 0;
467 }
468 else
469 {
470 idx += keyword_len;
471 }
Greg Clayton84c39662011-04-27 22:04:39 +0000472 }
473 }
474 bool done = type_str.empty();
475 //
476 idx = type_str.find_first_not_of (" \t");
477 if (idx > 0 && idx != std::string::npos)
478 type_str.erase (0, idx);
479 while (!done)
480 {
481 // Strip trailing spaces
482 if (type_str.empty())
483 done = true;
484 else
485 {
486 switch (type_str[type_str.size()-1])
487 {
488 case '*':
489 ++pointer_count;
490 // fall through...
491 case ' ':
492 case '\t':
493 type_str.erase(type_str.size()-1);
494 break;
495
496 case '&':
497 if (reference_count == 0)
498 {
499 reference_count = 1;
500 type_str.erase(type_str.size()-1);
501 }
502 else
503 {
504 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
505 result.SetStatus(eReturnStatusFailed);
506 return false;
507 }
508 break;
509
510 default:
511 done = true;
512 break;
513 }
514 }
515 }
516
517 ConstString lookup_type_name(type_str.c_str());
Jason Molendab57e4a12013-11-04 09:33:30 +0000518 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000519 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000520 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000521 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000522 if (sc.module_sp)
523 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000524 sc.module_sp->FindTypes (sc,
525 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000526 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000527 1,
528 type_list);
529 }
530 }
531 if (type_list.GetSize() == 0)
532 {
Greg Clayton29399a22012-04-06 17:41:13 +0000533 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000534 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000535 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000536 1,
537 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000538 }
Saleem Abdulrasoolba507b02015-10-18 19:34:38 +0000539
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000540 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000541 {
Sean Callananb92bd752015-10-01 16:28:02 +0000542 if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)))
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000543 {
Sean Callananb92bd752015-10-01 16:28:02 +0000544 clang::TypeDecl *tdecl = persistent_vars->GetPersistentType(ConstString(lookup_type_name));
Saleem Abdulrasoolba507b02015-10-18 19:34:38 +0000545
Sean Callananb92bd752015-10-01 16:28:02 +0000546 if (tdecl)
547 {
Saleem Abdulrasoolba507b02015-10-18 19:34:38 +0000548 clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),
549 reinterpret_cast<lldb::opaque_compiler_type_t>(const_cast<clang::Type*>(tdecl->getTypeForDecl())));
Sean Callananb92bd752015-10-01 16:28:02 +0000550 }
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000551 }
Greg Clayton84c39662011-04-27 22:04:39 +0000552 }
Saleem Abdulrasoolba507b02015-10-18 19:34:38 +0000553
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000554 if (clang_ast_type.IsValid() == false)
555 {
556 if (type_list.GetSize() == 0)
557 {
558 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
559 lookup_type_name.GetCString(),
560 view_as_type_cstr);
561 result.SetStatus(eReturnStatusFailed);
562 return false;
563 }
564 else
565 {
566 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton99558cc42015-08-24 23:46:31 +0000567 clang_ast_type = type_sp->GetFullCompilerType ();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000568 }
569 }
Greg Clayton84c39662011-04-27 22:04:39 +0000570
571 while (pointer_count > 0)
572 {
Greg Claytona1e5dc82015-08-11 22:53:00 +0000573 CompilerType pointer_type = clang_ast_type.GetPointerType();
Greg Clayton57ee3062013-07-11 22:46:58 +0000574 if (pointer_type.IsValid())
575 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000576 else
577 {
578 result.AppendError ("unable make a pointer type\n");
579 result.SetStatus(eReturnStatusFailed);
580 return false;
581 }
582 --pointer_count;
583 }
584
Enrico Granata1cd5e922015-01-28 00:07:51 +0000585 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
Greg Clayton84c39662011-04-27 22:04:39 +0000586
Greg Clayton1deb7962011-10-25 06:44:01 +0000587 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000588 {
589 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
590 view_as_type_cstr);
591 result.SetStatus(eReturnStatusFailed);
592 return false;
593 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000594
Greg Clayton1deb7962011-10-25 06:44:01 +0000595 if (!m_format_options.GetCountValue().OptionWasSet())
596 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000597 }
598 else
599 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000600 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000601 }
602
603 // Look for invalid combinations of settings
604 if (error.Fail())
605 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000606 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000607 result.SetStatus(eReturnStatusFailed);
608 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000609 }
610
Greg Clayton82f4cf42011-10-26 04:32:38 +0000611 lldb::addr_t addr;
612 size_t total_byte_size = 0;
613 if (argc == 0)
614 {
615 // Use the last address and byte size and all options as they were
616 // if no options have been set
617 addr = m_next_addr;
618 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000619 clang_ast_type = m_prev_clang_ast_type;
620 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000621 !m_memory_options.AnyOptionWasSet() &&
622 !m_outfile_options.AnyOptionWasSet() &&
623 !m_varobj_options.AnyOptionWasSet())
624 {
625 m_format_options = m_prev_format_options;
626 m_memory_options = m_prev_memory_options;
627 m_outfile_options = m_prev_outfile_options;
628 m_varobj_options = m_prev_varobj_options;
629 }
630 }
631
Greg Clayton1deb7962011-10-25 06:44:01 +0000632 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000633
634 // TODO For non-8-bit byte addressable architectures this needs to be
635 // revisited to fully support all lldb's range of formatting options.
636 // Furthermore code memory reads (for those architectures) will not
637 // be correctly formatted even w/o formatting options.
638 size_t item_byte_size =
639 target->GetArchitecture().GetDataByteSize() > 1 ?
640 target->GetArchitecture().GetDataByteSize() :
641 m_format_options.GetByteSizeValue().GetCurrentValue();
642
Greg Clayton68ebae62011-04-28 20:55:26 +0000643 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000644
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000645 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000646 {
647 total_byte_size = item_count * item_byte_size;
648 if (total_byte_size == 0)
649 total_byte_size = 32;
650 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000651
Greg Clayton82f4cf42011-10-26 04:32:38 +0000652 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000653 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000654
655 if (addr == LLDB_INVALID_ADDRESS)
656 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000657 result.AppendError("invalid start address expression.");
658 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000659 result.SetStatus(eReturnStatusFailed);
660 return false;
661 }
662
663 if (argc == 2)
664 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000665 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000666 if (end_addr == LLDB_INVALID_ADDRESS)
667 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000668 result.AppendError("invalid end address expression.");
669 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000670 result.SetStatus(eReturnStatusFailed);
671 return false;
672 }
673 else if (end_addr <= addr)
674 {
Daniel Malead01b2952012-11-29 21:49:15 +0000675 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 +0000676 result.SetStatus(eReturnStatusFailed);
677 return false;
678 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000679 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000680 {
Greg Clayton6fea17e2014-03-03 19:15:20 +0000681 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 +0000682 result.SetStatus(eReturnStatusFailed);
683 return false;
684 }
685
686 total_byte_size = end_addr - addr;
687 item_count = total_byte_size / item_byte_size;
688 }
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000689
Enrico Granatad325bf92013-06-04 22:54:16 +0000690 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
691
692 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000693 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000694 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
695 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
696 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 +0000697 return false;
698 }
699
Greg Clayton84c39662011-04-27 22:04:39 +0000700 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000701 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000702 if (clang_ast_type.GetOpaqueQualType())
703 {
704 // Make sure we don't display our type as ASCII bytes like the default memory read
705 if (m_format_options.GetFormatValue().OptionWasSet() == false)
706 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
707
Enrico Granata1cd5e922015-01-28 00:07:51 +0000708 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
Enrico Granata7a336212015-10-29 23:40:24 +0000709
710 if (argc > 0)
711 addr = addr + (clang_ast_type.GetByteSize(nullptr) * m_memory_options.m_offset.GetCurrentValue());
Greg Clayton2e1f7452012-12-15 02:08:17 +0000712 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000713 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000714 {
Greg Clayton84c39662011-04-27 22:04:39 +0000715 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000716 if (data_sp->GetBytes() == NULL)
717 {
Virgile Belloffeba252014-03-08 17:15:35 +0000718 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size);
Greg Clayton46a44262013-07-24 18:17:35 +0000719 result.SetStatus(eReturnStatusFailed);
720 return false;
721 }
722
Greg Claytone72dfb32012-02-24 01:59:29 +0000723 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000724 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000725 if (bytes_read == 0)
726 {
Greg Clayton57f06302012-05-25 17:05:55 +0000727 const char *error_cstr = error.AsCString();
728 if (error_cstr && error_cstr[0])
729 {
730 result.AppendError(error_cstr);
731 }
732 else
733 {
Daniel Malead01b2952012-11-29 21:49:15 +0000734 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000735 }
Greg Clayton84c39662011-04-27 22:04:39 +0000736 result.SetStatus(eReturnStatusFailed);
737 return false;
738 }
739
740 if (bytes_read < total_byte_size)
Greg Clayton6fea17e2014-03-03 19:15:20 +0000741 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 +0000742 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000743 else
744 {
745 // we treat c-strings as a special case because they do not have a fixed size
746 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
747 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
748 else
749 item_byte_size = target->GetMaximumSizeOfStringSummary();
750 if (!m_format_options.GetCountValue().OptionWasSet())
751 item_count = 1;
752 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000753 if (data_sp->GetBytes() == NULL)
754 {
755 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));
756 result.SetStatus(eReturnStatusFailed);
757 return false;
758 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000759 uint8_t *data_ptr = data_sp->GetBytes();
760 auto data_addr = addr;
761 auto count = item_count;
762 item_count = 0;
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000763 bool break_on_no_NULL = false;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000764 while (item_count < count)
765 {
766 std::string buffer;
767 buffer.resize(item_byte_size+1,0);
768 Error error;
769 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
770 if (error.Fail())
771 {
772 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
773 result.SetStatus(eReturnStatusFailed);
774 return false;
775 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000776
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000777 if (item_byte_size == read)
778 {
779 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000780 --read;
781 break_on_no_NULL = true;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000782 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000783 else
784 ++read; // account for final NULL byte
785
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000786 memcpy(data_ptr, &buffer[0], read);
787 data_ptr += read;
788 data_addr += read;
789 bytes_read += read;
790 item_count++; // if we break early we know we only read item_count strings
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000791
792 if (break_on_no_NULL)
793 break;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000794 }
795 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
796 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000797
Greg Clayton2e1f7452012-12-15 02:08:17 +0000798 m_next_addr = addr + bytes_read;
799 m_prev_byte_size = bytes_read;
800 m_prev_format_options = m_format_options;
801 m_prev_memory_options = m_memory_options;
802 m_prev_outfile_options = m_outfile_options;
803 m_prev_varobj_options = m_varobj_options;
804 m_prev_clang_ast_type = clang_ast_type;
805
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000806 StreamFile outfile_stream;
807 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000808 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
809 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000810 {
811 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000812 outfile_spec.GetPath (path, sizeof(path));
813
814 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
815 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
816 if (append)
817 open_options |= File::eOpenOptionAppend;
818
819 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000820 {
Greg Clayton84c39662011-04-27 22:04:39 +0000821 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000822 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000823 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000824 if (bytes_written > 0)
825 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000826 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000827 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000828 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000829 path);
830 return true;
831 }
832 else
833 {
Daniel Malead01b2952012-11-29 21:49:15 +0000834 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000835 result.SetStatus(eReturnStatusFailed);
836 return false;
837 }
838 }
839 else
840 {
841 // We are going to write ASCII to the file just point the
842 // output_stream to our outfile_stream...
843 output_stream = &outfile_stream;
844 }
845 }
846 else
847 {
Greg Clayton84c39662011-04-27 22:04:39 +0000848 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000849 result.SetStatus(eReturnStatusFailed);
850 return false;
851 }
852 }
853 else
854 {
855 output_stream = &result.GetOutputStream();
856 }
857
Greg Clayton84c39662011-04-27 22:04:39 +0000858
Greg Claytonf9fc6092013-01-09 19:44:40 +0000859 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000860 if (clang_ast_type.GetOpaqueQualType())
861 {
862 for (uint32_t i = 0; i<item_count; ++i)
863 {
864 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000865 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000866 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000867 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000868 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000869 name_strm.GetString().c_str(),
870 address,
871 clang_ast_type));
872 if (valobj_sp)
873 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000874 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000875 if (format != eFormatDefault)
876 valobj_sp->SetFormat (format);
877
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000878 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000879
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000880 valobj_sp->Dump(*output_stream,options);
Greg Clayton84c39662011-04-27 22:04:39 +0000881 }
882 else
883 {
884 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
885 view_as_type_cstr,
886 name_strm.GetString().c_str());
887 result.SetStatus(eReturnStatusFailed);
888 return false;
889 }
890 }
891 return true;
892 }
893
894 result.SetStatus(eReturnStatusSuccessFinishResult);
895 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000896 target->GetArchitecture().GetByteOrder(),
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000897 target->GetArchitecture().GetAddressByteSize(),
898 target->GetArchitecture().GetDataByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000899
900 Format format = m_format_options.GetFormat();
901 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
Enrico Granata0947a6e2013-10-29 23:04:29 +0000902 && (item_byte_size != 1))
Enrico Granata31898912013-05-21 17:39:04 +0000903 {
Enrico Granata0947a6e2013-10-29 23:04:29 +0000904 // if a count was not passed, or it is 1
905 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
906 {
907 // this turns requests such as
908 // memory read -fc -s10 -c1 *charPtrPtr
909 // which make no sense (what is a char of size 10?)
910 // into a request for fetching 10 chars of size 1 from the same memory location
911 format = eFormatCharArray;
912 item_count = item_byte_size;
913 item_byte_size = 1;
914 }
915 else
916 {
917 // here we passed a count, and it was not 1
918 // so we have a byte_size and a count
919 // we could well multiply those, but instead let's just fail
Greg Clayton6fea17e2014-03-03 19:15:20 +0000920 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
Enrico Granata0947a6e2013-10-29 23:04:29 +0000921 result.SetStatus(eReturnStatusFailed);
922 return false;
923 }
Enrico Granata31898912013-05-21 17:39:04 +0000924 }
Greg Clayton84c39662011-04-27 22:04:39 +0000925
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000926 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000927 size_t bytes_dumped = data.Dump (output_stream,
928 0,
Enrico Granata31898912013-05-21 17:39:04 +0000929 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000930 item_byte_size,
931 item_count,
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000932 num_per_line / target->GetArchitecture().GetDataByteSize(),
Greg Claytonc7bece562013-01-25 18:06:21 +0000933 addr,
934 0,
935 0,
936 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000937 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000938 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000939 return true;
940 }
941
Greg Clayton84c39662011-04-27 22:04:39 +0000942 OptionGroupOptions m_option_group;
943 OptionGroupFormat m_format_options;
944 OptionGroupReadMemory m_memory_options;
945 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000946 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000947 lldb::addr_t m_next_addr;
948 lldb::addr_t m_prev_byte_size;
949 OptionGroupFormat m_prev_format_options;
950 OptionGroupReadMemory m_prev_memory_options;
951 OptionGroupOutputFile m_prev_outfile_options;
952 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Claytona1e5dc82015-08-11 22:53:00 +0000953 CompilerType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000954};
955
Enrico Granata53468432013-11-13 02:18:44 +0000956OptionDefinition
957g_memory_find_option_table[] =
958{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000959 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
960 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
961 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."},
962 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, 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 +0000963};
964
Enrico Granata53468432013-11-13 02:18:44 +0000965//----------------------------------------------------------------------
966// Find the specified data in memory
967//----------------------------------------------------------------------
968class CommandObjectMemoryFind : public CommandObjectParsed
969{
970public:
971
972 class OptionGroupFindMemory : public OptionGroup
973 {
974 public:
975 OptionGroupFindMemory () :
976 OptionGroup(),
977 m_count(1),
Enrico Granata8d81a842013-11-13 20:08:30 +0000978 m_offset(0)
Enrico Granata53468432013-11-13 02:18:44 +0000979 {
980 }
981
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000982 ~OptionGroupFindMemory () override
Enrico Granata53468432013-11-13 02:18:44 +0000983 {
984 }
985
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000986 uint32_t
987 GetNumDefinitions () override
Enrico Granata53468432013-11-13 02:18:44 +0000988 {
989 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
990 }
991
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000992 const OptionDefinition*
993 GetDefinitions () override
Enrico Granata53468432013-11-13 02:18:44 +0000994 {
995 return g_memory_find_option_table;
996 }
997
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000998 Error
Enrico Granata53468432013-11-13 02:18:44 +0000999 SetOptionValue (CommandInterpreter &interpreter,
1000 uint32_t option_idx,
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001001 const char *option_arg) override
Enrico Granata53468432013-11-13 02:18:44 +00001002 {
1003 Error error;
1004 const int short_option = g_memory_find_option_table[option_idx].short_option;
1005
1006 switch (short_option)
1007 {
1008 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001009 m_expr.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +00001010 break;
1011
1012 case 's':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001013 m_string.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +00001014 break;
1015
1016 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001017 if (m_count.SetValueFromString(option_arg).Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001018 error.SetErrorString("unrecognized value for count");
1019 break;
1020
Enrico Granata8d81a842013-11-13 20:08:30 +00001021 case 'o':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001022 if (m_offset.SetValueFromString(option_arg).Fail())
Enrico Granata8d81a842013-11-13 20:08:30 +00001023 error.SetErrorString("unrecognized value for dump-offset");
1024 break;
1025
Enrico Granata53468432013-11-13 02:18:44 +00001026 default:
1027 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1028 break;
1029 }
1030 return error;
1031 }
1032
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001033 void
1034 OptionParsingStarting (CommandInterpreter &interpreter) override
Enrico Granata53468432013-11-13 02:18:44 +00001035 {
1036 m_expr.Clear();
1037 m_string.Clear();
1038 m_count.Clear();
Enrico Granata53468432013-11-13 02:18:44 +00001039 }
1040
1041 OptionValueString m_expr;
1042 OptionValueString m_string;
1043 OptionValueUInt64 m_count;
Enrico Granata8d81a842013-11-13 20:08:30 +00001044 OptionValueUInt64 m_offset;
Enrico Granata53468432013-11-13 02:18:44 +00001045 };
1046
1047 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1048 CommandObjectParsed (interpreter,
1049 "memory find",
1050 "Find a value in the memory of the process being debugged.",
1051 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001052 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Enrico Granata53468432013-11-13 02:18:44 +00001053 m_option_group (interpreter),
1054 m_memory_options ()
1055 {
1056 CommandArgumentEntry arg1;
1057 CommandArgumentEntry arg2;
1058 CommandArgumentData addr_arg;
1059 CommandArgumentData value_arg;
1060
1061 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001062 addr_arg.arg_type = eArgTypeAddressOrExpression;
Enrico Granata53468432013-11-13 02:18:44 +00001063 addr_arg.arg_repetition = eArgRepeatPlain;
1064
1065 // There is only one variant this argument could be; put it into the argument entry.
1066 arg1.push_back (addr_arg);
1067
1068 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001069 value_arg.arg_type = eArgTypeAddressOrExpression;
1070 value_arg.arg_repetition = eArgRepeatPlain;
Enrico Granata53468432013-11-13 02:18:44 +00001071
1072 // There is only one variant this argument could be; put it into the argument entry.
1073 arg2.push_back (value_arg);
1074
1075 // Push the data for the first argument into the m_arguments vector.
1076 m_arguments.push_back (arg1);
1077 m_arguments.push_back (arg2);
1078
1079 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1080 m_option_group.Finalize();
1081 }
1082
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001083 ~CommandObjectMemoryFind () override
Enrico Granata53468432013-11-13 02:18:44 +00001084 {
1085 }
1086
1087 Options *
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001088 GetOptions () override
Enrico Granata53468432013-11-13 02:18:44 +00001089 {
1090 return &m_option_group;
1091 }
1092
1093protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001094 bool
1095 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata53468432013-11-13 02:18:44 +00001096 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001097 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Enrico Granata53468432013-11-13 02:18:44 +00001098 Process *process = m_exe_ctx.GetProcessPtr();
1099
1100 const size_t argc = command.GetArgumentCount();
1101
1102 if (argc != 2)
1103 {
Enrico Granata6e49c482013-11-13 02:22:24 +00001104 result.AppendError("two addresses needed for memory find");
Enrico Granata53468432013-11-13 02:18:44 +00001105 return false;
1106 }
1107
1108 Error error;
1109 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1110 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1111 {
1112 result.AppendError("invalid low address");
1113 return false;
1114 }
1115 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1116 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1117 {
Ed Maste47a8a5e2014-09-06 11:29:08 +00001118 result.AppendError("invalid high address");
Enrico Granata53468432013-11-13 02:18:44 +00001119 return false;
1120 }
1121
1122 if (high_addr <= low_addr)
1123 {
1124 result.AppendError("starting address must be smaller than ending address");
1125 return false;
1126 }
1127
1128 lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1129
1130 DataBufferHeap buffer;
1131
1132 if (m_memory_options.m_string.OptionWasSet())
1133 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1134 else if (m_memory_options.m_expr.OptionWasSet())
1135 {
1136 StackFrame* frame = m_exe_ctx.GetFramePtr();
1137 ValueObjectSP result_sp;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001138 if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
1139 result_sp.get())
Enrico Granata53468432013-11-13 02:18:44 +00001140 {
1141 uint64_t value = result_sp->GetValueAsUnsigned(0);
Greg Clayton99558cc42015-08-24 23:46:31 +00001142 switch (result_sp->GetCompilerType().GetByteSize(nullptr))
Enrico Granata53468432013-11-13 02:18:44 +00001143 {
1144 case 1: {
1145 uint8_t byte = (uint8_t)value;
1146 buffer.CopyData(&byte,1);
1147 }
1148 break;
1149 case 2: {
1150 uint16_t word = (uint16_t)value;
1151 buffer.CopyData(&word,2);
1152 }
1153 break;
1154 case 4: {
1155 uint32_t lword = (uint32_t)value;
1156 buffer.CopyData(&lword,4);
1157 }
1158 break;
1159 case 8: {
1160 buffer.CopyData(&value, 8);
1161 }
1162 break;
1163 case 3:
1164 case 5:
1165 case 6:
1166 case 7:
1167 result.AppendError("unknown type. pass a string instead");
1168 return false;
1169 default:
Enrico Granata0b3b9872015-08-03 18:51:39 +00001170 result.AppendError("result size larger than 8 bytes. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001171 return false;
1172 }
1173 }
1174 else
1175 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001176 result.AppendError("expression evaluation failed. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001177 return false;
1178 }
1179 }
1180 else
1181 {
1182 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1183 return false;
1184 }
1185
1186 size_t count = m_memory_options.m_count.GetCurrentValue();
1187 found_location = low_addr;
1188 bool ever_found = false;
1189 while (count)
1190 {
1191 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1192 if (found_location == LLDB_INVALID_ADDRESS)
1193 {
1194 if (!ever_found)
1195 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001196 result.AppendMessage("data not found within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001197 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1198 }
1199 else
Enrico Granata0b3b9872015-08-03 18:51:39 +00001200 result.AppendMessage("no more matches within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001201 break;
1202 }
Enrico Granata0b3b9872015-08-03 18:51:39 +00001203 result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location);
Enrico Granata8d81a842013-11-13 20:08:30 +00001204
1205 DataBufferHeap dumpbuffer(32,0);
1206 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1207 if (!error.Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001208 {
Enrico Granata8d81a842013-11-13 20:08:30 +00001209 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1210 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1211 result.GetOutputStream().EOL();
Enrico Granata53468432013-11-13 02:18:44 +00001212 }
Enrico Granata8d81a842013-11-13 20:08:30 +00001213
Enrico Granata53468432013-11-13 02:18:44 +00001214 --count;
1215 found_location++;
1216 ever_found = true;
1217 }
1218
1219 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1220 return true;
1221 }
1222
1223 lldb::addr_t
1224 Search (lldb::addr_t low,
1225 lldb::addr_t high,
1226 uint8_t* buffer,
1227 size_t buffer_size)
1228 {
1229 Process *process = m_exe_ctx.GetProcessPtr();
1230 DataBufferHeap heap(buffer_size, 0);
Enrico Granata53468432013-11-13 02:18:44 +00001231 for (auto ptr = low;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001232 ptr < high;
1233 ptr++)
Enrico Granata53468432013-11-13 02:18:44 +00001234 {
1235 Error error;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001236 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
Enrico Granata53468432013-11-13 02:18:44 +00001237 if (error.Fail())
1238 return LLDB_INVALID_ADDRESS;
1239 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
Enrico Granata0b3b9872015-08-03 18:51:39 +00001240 return ptr;
Enrico Granata53468432013-11-13 02:18:44 +00001241 }
1242 return LLDB_INVALID_ADDRESS;
1243 }
1244
1245 OptionGroupOptions m_option_group;
1246 OptionGroupFindMemory m_memory_options;
1247};
1248
Greg Clayton1deb7962011-10-25 06:44:01 +00001249
1250OptionDefinition
1251g_memory_write_option_table[] =
1252{
Zachary Turnerd37221d2014-07-09 16:31:49 +00001253{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
Bruce Mitchener350b78e2014-07-10 14:45:57 +00001254{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."},
Greg Clayton1deb7962011-10-25 06:44:01 +00001255};
1256
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001257//----------------------------------------------------------------------
1258// Write memory to the inferior process
1259//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001260class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001261{
1262public:
1263
Greg Clayton1deb7962011-10-25 06:44:01 +00001264 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001265 {
1266 public:
Greg Clayton1deb7962011-10-25 06:44:01 +00001267 OptionGroupWriteMemory () :
1268 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001269 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001270 }
1271
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001272 ~OptionGroupWriteMemory () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001273 {
1274 }
1275
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001276 uint32_t
1277 GetNumDefinitions () override
Greg Clayton1deb7962011-10-25 06:44:01 +00001278 {
1279 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1280 }
Enrico Granata53468432013-11-13 02:18:44 +00001281
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001282 const OptionDefinition*
1283 GetDefinitions () override
Greg Clayton1deb7962011-10-25 06:44:01 +00001284 {
1285 return g_memory_write_option_table;
1286 }
Enrico Granata53468432013-11-13 02:18:44 +00001287
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001288 Error
Greg Clayton1deb7962011-10-25 06:44:01 +00001289 SetOptionValue (CommandInterpreter &interpreter,
1290 uint32_t option_idx,
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001291 const char *option_arg) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001292 {
1293 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001294 const int short_option = g_memory_write_option_table[option_idx].short_option;
Enrico Granata53468432013-11-13 02:18:44 +00001295
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001296 switch (short_option)
1297 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001298 case 'i':
1299 m_infile.SetFile (option_arg, true);
1300 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001301 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001302 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +00001303 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001304 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001305 break;
Enrico Granata53468432013-11-13 02:18:44 +00001306
Greg Clayton1deb7962011-10-25 06:44:01 +00001307 case 'o':
1308 {
1309 bool success;
Vince Harron5275aaa2015-01-15 20:08:35 +00001310 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
Greg Clayton1deb7962011-10-25 06:44:01 +00001311 if (!success)
1312 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001313 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +00001314 }
1315 }
1316 break;
1317
1318 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001319 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +00001320 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001321 }
1322 return error;
1323 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001324
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001325 void
1326 OptionParsingStarting (CommandInterpreter &interpreter) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001327 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001328 m_infile.Clear();
1329 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001330 }
1331
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001332 FileSpec m_infile;
1333 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001334 };
1335
Greg Claytona7015092010-09-18 01:14:36 +00001336 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001337 CommandObjectParsed (interpreter,
1338 "memory write",
1339 "Write to the memory of the process being debugged.",
1340 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001341 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001342 m_option_group (interpreter),
1343 m_format_options (eFormatBytes, 1, UINT64_MAX),
1344 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001345 {
Caroline Tice405fe672010-10-04 22:28:36 +00001346 CommandArgumentEntry arg1;
1347 CommandArgumentEntry arg2;
1348 CommandArgumentData addr_arg;
1349 CommandArgumentData value_arg;
1350
1351 // Define the first (and only) variant of this arg.
1352 addr_arg.arg_type = eArgTypeAddress;
1353 addr_arg.arg_repetition = eArgRepeatPlain;
1354
1355 // There is only one variant this argument could be; put it into the argument entry.
1356 arg1.push_back (addr_arg);
1357
1358 // Define the first (and only) variant of this arg.
1359 value_arg.arg_type = eArgTypeValue;
1360 value_arg.arg_repetition = eArgRepeatPlus;
1361
1362 // There is only one variant this argument could be; put it into the argument entry.
1363 arg2.push_back (value_arg);
1364
1365 // Push the data for the first argument into the m_arguments vector.
1366 m_arguments.push_back (arg1);
1367 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001368
1369 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1370 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1371 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1372 m_option_group.Finalize();
1373
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001374 }
1375
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001376 ~CommandObjectMemoryWrite () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001377 {
1378 }
1379
1380 Options *
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001381 GetOptions () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001382 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001383 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001384 }
1385
1386 bool
1387 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1388 {
1389 if (total_byte_size > 8)
1390 return false;
1391
1392 if (total_byte_size == 8)
1393 return true;
1394
1395 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1396 return uval64 <= max;
1397 }
1398
1399 bool
1400 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1401 {
1402 if (total_byte_size > 8)
1403 return false;
1404
1405 if (total_byte_size == 8)
1406 return true;
1407
1408 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1409 const int64_t min = ~(max);
1410 return min <= sval64 && sval64 <= max;
1411 }
1412
Jim Ingham5a988412012-06-08 21:56:10 +00001413protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001414 bool
1415 DoExecute (Args& command, CommandReturnObject &result) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001416 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001417 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +00001418 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001419
1420 const size_t argc = command.GetArgumentCount();
1421
Greg Clayton1deb7962011-10-25 06:44:01 +00001422 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001423 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001424 if (argc < 1)
1425 {
1426 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1427 result.SetStatus(eReturnStatusFailed);
1428 return false;
1429 }
1430 }
1431 else if (argc < 2)
1432 {
1433 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 +00001434 result.SetStatus(eReturnStatusFailed);
1435 return false;
1436 }
1437
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001438 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001439 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1440 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001441
Greg Clayton1deb7962011-10-25 06:44:01 +00001442 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1443 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001444
Greg Claytonb9d5df52012-12-06 22:49:16 +00001445 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001446 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001447 command.GetArgumentAtIndex(0),
1448 LLDB_INVALID_ADDRESS,
1449 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001450
1451 if (addr == LLDB_INVALID_ADDRESS)
1452 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001453 result.AppendError("invalid address expression\n");
1454 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001455 result.SetStatus(eReturnStatusFailed);
1456 return false;
1457 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001458
Greg Clayton1deb7962011-10-25 06:44:01 +00001459 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001460 {
1461 size_t length = SIZE_MAX;
Jason Molenda250b1b892015-02-03 23:39:47 +00001462 if (item_byte_size > 1)
Greg Clayton1deb7962011-10-25 06:44:01 +00001463 length = item_byte_size;
1464 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001465 if (data_sp)
1466 {
1467 length = data_sp->GetByteSize();
1468 if (length > 0)
1469 {
1470 Error error;
1471 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1472
1473 if (bytes_written == length)
1474 {
1475 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001476 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001477 result.SetStatus(eReturnStatusSuccessFinishResult);
1478 }
1479 else if (bytes_written > 0)
1480 {
1481 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001482 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 +00001483 result.SetStatus(eReturnStatusSuccessFinishResult);
1484 }
1485 else
1486 {
Daniel Malead01b2952012-11-29 21:49:15 +00001487 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001488 result.SetStatus(eReturnStatusFailed);
1489 }
1490 }
1491 }
1492 else
1493 {
1494 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1495 result.SetStatus(eReturnStatusFailed);
1496 }
1497 return result.Succeeded();
1498 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001499 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001500 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001501 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001502 item_byte_size = buffer.GetAddressByteSize();
1503 else
1504 item_byte_size = 1;
1505 }
1506
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001507 command.Shift(); // shift off the address argument
1508 uint64_t uval64;
1509 int64_t sval64;
1510 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001511 const size_t num_value_args = command.GetArgumentCount();
1512 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001513 {
1514 const char *value_str = command.GetArgumentAtIndex(i);
1515
Greg Clayton1deb7962011-10-25 06:44:01 +00001516 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001517 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001518 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001519 case eFormatFloat: // TODO: add support for floats soon
1520 case eFormatCharPrintable:
1521 case eFormatBytesWithASCII:
1522 case eFormatComplex:
1523 case eFormatEnum:
1524 case eFormatUnicode16:
1525 case eFormatUnicode32:
1526 case eFormatVectorOfChar:
1527 case eFormatVectorOfSInt8:
1528 case eFormatVectorOfUInt8:
1529 case eFormatVectorOfSInt16:
1530 case eFormatVectorOfUInt16:
1531 case eFormatVectorOfSInt32:
1532 case eFormatVectorOfUInt32:
1533 case eFormatVectorOfSInt64:
1534 case eFormatVectorOfUInt64:
Enrico Granata15560772015-10-16 23:42:04 +00001535 case eFormatVectorOfFloat16:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001536 case eFormatVectorOfFloat32:
1537 case eFormatVectorOfFloat64:
1538 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001539 case eFormatOSType:
1540 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001541 case eFormatAddressInfo:
1542 case eFormatHexFloat:
1543 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001544 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001545 result.AppendError("unsupported format for writing memory");
1546 result.SetStatus(eReturnStatusFailed);
1547 return false;
1548
1549 case eFormatDefault:
1550 case eFormatBytes:
1551 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001552 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001553 case eFormatPointer:
1554
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001555 // Decode hex bytes
Vince Harron5275aaa2015-01-15 20:08:35 +00001556 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001557 if (!success)
1558 {
1559 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1560 result.SetStatus(eReturnStatusFailed);
1561 return false;
1562 }
1563 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1564 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001565 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 +00001566 result.SetStatus(eReturnStatusFailed);
1567 return false;
1568 }
1569 buffer.PutMaxHex64 (uval64, item_byte_size);
1570 break;
1571
1572 case eFormatBoolean:
1573 uval64 = Args::StringToBoolean(value_str, false, &success);
1574 if (!success)
1575 {
1576 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1577 result.SetStatus(eReturnStatusFailed);
1578 return false;
1579 }
1580 buffer.PutMaxHex64 (uval64, item_byte_size);
1581 break;
1582
1583 case eFormatBinary:
Vince Harron5275aaa2015-01-15 20:08:35 +00001584 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001585 if (!success)
1586 {
1587 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1588 result.SetStatus(eReturnStatusFailed);
1589 return false;
1590 }
1591 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1592 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001593 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 +00001594 result.SetStatus(eReturnStatusFailed);
1595 return false;
1596 }
1597 buffer.PutMaxHex64 (uval64, item_byte_size);
1598 break;
1599
Greg Clayton4e4294b2011-06-17 23:50:44 +00001600 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001601 case eFormatChar:
1602 case eFormatCString:
1603 if (value_str[0])
1604 {
1605 size_t len = strlen (value_str);
1606 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001607 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001608 ++len;
1609 Error error;
1610 if (process->WriteMemory (addr, value_str, len, error) == len)
1611 {
1612 addr += len;
1613 }
1614 else
1615 {
Daniel Malead01b2952012-11-29 21:49:15 +00001616 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001617 result.SetStatus(eReturnStatusFailed);
1618 return false;
1619 }
1620 }
1621 break;
1622
1623 case eFormatDecimal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001624 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001625 if (!success)
1626 {
1627 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1628 result.SetStatus(eReturnStatusFailed);
1629 return false;
1630 }
1631 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1632 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001633 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 +00001634 result.SetStatus(eReturnStatusFailed);
1635 return false;
1636 }
1637 buffer.PutMaxHex64 (sval64, item_byte_size);
1638 break;
1639
1640 case eFormatUnsigned:
Vince Harron5275aaa2015-01-15 20:08:35 +00001641 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001642 if (!success)
1643 {
1644 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1645 result.SetStatus(eReturnStatusFailed);
1646 return false;
1647 }
1648 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1649 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001650 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 +00001651 result.SetStatus(eReturnStatusFailed);
1652 return false;
1653 }
1654 buffer.PutMaxHex64 (uval64, item_byte_size);
1655 break;
1656
1657 case eFormatOctal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001658 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001659 if (!success)
1660 {
1661 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1662 result.SetStatus(eReturnStatusFailed);
1663 return false;
1664 }
1665 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1666 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001667 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 +00001668 result.SetStatus(eReturnStatusFailed);
1669 return false;
1670 }
1671 buffer.PutMaxHex64 (uval64, item_byte_size);
1672 break;
1673 }
1674 }
1675
1676 if (!buffer.GetString().empty())
1677 {
1678 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001679 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001680 return true;
1681 else
1682 {
Daniel Malead01b2952012-11-29 21:49:15 +00001683 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001684 result.SetStatus(eReturnStatusFailed);
1685 return false;
1686 }
1687 }
1688 return true;
1689 }
1690
Greg Clayton1deb7962011-10-25 06:44:01 +00001691 OptionGroupOptions m_option_group;
1692 OptionGroupFormat m_format_options;
1693 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001694};
1695
Kuba Breckabeed8212014-09-04 01:03:18 +00001696//----------------------------------------------------------------------
1697// Get malloc/free history of a memory address.
1698//----------------------------------------------------------------------
1699class CommandObjectMemoryHistory : public CommandObjectParsed
1700{
1701public:
1702
1703 CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1704 CommandObjectParsed (interpreter,
1705 "memory history",
1706 "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1707 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001708 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | eCommandProcessMustBeLaunched)
Kuba Breckabeed8212014-09-04 01:03:18 +00001709 {
1710 CommandArgumentEntry arg1;
1711 CommandArgumentData addr_arg;
1712
1713 // Define the first (and only) variant of this arg.
1714 addr_arg.arg_type = eArgTypeAddress;
1715 addr_arg.arg_repetition = eArgRepeatPlain;
1716
1717 // There is only one variant this argument could be; put it into the argument entry.
1718 arg1.push_back (addr_arg);
1719
1720 // Push the data for the first argument into the m_arguments vector.
1721 m_arguments.push_back (arg1);
1722 }
1723
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001724 ~CommandObjectMemoryHistory () override
Kuba Breckabeed8212014-09-04 01:03:18 +00001725 {
1726 }
1727
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001728 const char *
1729 GetRepeatCommand (Args &current_command_args, uint32_t index) override
Kuba Breckabeed8212014-09-04 01:03:18 +00001730 {
1731 return m_cmd_name.c_str();
1732 }
1733
1734protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001735 bool
1736 DoExecute (Args& command, CommandReturnObject &result) override
Kuba Breckabeed8212014-09-04 01:03:18 +00001737 {
1738 const size_t argc = command.GetArgumentCount();
1739
1740 if (argc == 0 || argc > 1)
1741 {
1742 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1743 result.SetStatus(eReturnStatusFailed);
1744 return false;
1745 }
1746
1747 Error error;
1748 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1749 command.GetArgumentAtIndex(0),
1750 LLDB_INVALID_ADDRESS,
1751 &error);
1752
1753 if (addr == LLDB_INVALID_ADDRESS)
1754 {
1755 result.AppendError("invalid address expression");
1756 result.AppendError(error.AsCString());
1757 result.SetStatus(eReturnStatusFailed);
1758 return false;
1759 }
1760
1761 Stream *output_stream = &result.GetOutputStream();
1762
1763 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1764 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1765
1766 if (! memory_history.get())
1767 {
1768 result.AppendError("no available memory history provider");
1769 result.SetStatus(eReturnStatusFailed);
1770 return false;
1771 }
1772
1773 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1774
1775 for (auto thread : thread_list) {
1776 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1777 }
1778
1779 result.SetStatus(eReturnStatusSuccessFinishResult);
1780
1781 return true;
1782 }
1783
1784};
1785
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001786
1787//-------------------------------------------------------------------------
1788// CommandObjectMemory
1789//-------------------------------------------------------------------------
1790
Greg Clayton66111032010-06-23 01:19:29 +00001791CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001792 CommandObjectMultiword (interpreter,
1793 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001794 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001795 "memory <subcommand> [<subcommand-options>]")
1796{
Enrico Granata53468432013-11-13 02:18:44 +00001797 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001798 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1799 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Kuba Breckabeed8212014-09-04 01:03:18 +00001800 LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001801}
1802
1803CommandObjectMemory::~CommandObjectMemory ()
1804{
1805}