blob: 486a5eb912af9dbfcfa49e057c2de4cda86c80c3 [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"
Kuba Breckabeed8212014-09-04 01:03:18 +000036#include "lldb/Target/MemoryHistory.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037#include "lldb/Target/Process.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000038#include "lldb/Target/StackFrame.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000039#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040
41using namespace lldb;
42using namespace lldb_private;
43
Greg Clayton68ebae62011-04-28 20:55:26 +000044static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000045g_option_table[] =
46{
Zachary Turnerd37221d2014-07-09 16:31:49 +000047 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
48 { 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."},
49 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton2346fcf2012-11-02 21:14:58 +000050 { LLDB_OPT_SET_1|
51 LLDB_OPT_SET_2|
Zachary Turnerd37221d2014-07-09 16:31:49 +000052 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 +000053};
54
55
56
57class OptionGroupReadMemory : public OptionGroup
58{
59public:
60
61 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000062 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000063 m_output_as_binary (false),
64 m_view_as_type()
65 {
66 }
67
68 virtual
69 ~OptionGroupReadMemory ()
70 {
71 }
72
73
74 virtual uint32_t
75 GetNumDefinitions ()
76 {
77 return sizeof (g_option_table) / sizeof (OptionDefinition);
78 }
79
80 virtual const OptionDefinition*
81 GetDefinitions ()
82 {
83 return g_option_table;
84 }
85
86 virtual Error
87 SetOptionValue (CommandInterpreter &interpreter,
88 uint32_t option_idx,
89 const char *option_arg)
90 {
91 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000092 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000093
94 switch (short_option)
95 {
96 case 'l':
97 error = m_num_per_line.SetValueFromCString (option_arg);
98 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +000099 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000100 break;
Greg Clayton1deb7962011-10-25 06:44:01 +0000101
Greg Clayton84c39662011-04-27 22:04:39 +0000102 case 'b':
103 m_output_as_binary = true;
104 break;
105
106 case 't':
107 error = m_view_as_type.SetValueFromCString (option_arg);
108 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000109
110 case 'r':
111 m_force = true;
112 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000113
114 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000115 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000116 break;
117 }
118 return error;
119 }
120
121 virtual void
122 OptionParsingStarting (CommandInterpreter &interpreter)
123 {
Greg Clayton84c39662011-04-27 22:04:39 +0000124 m_num_per_line.Clear();
125 m_output_as_binary = false;
126 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000127 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000128 }
129
Greg Clayton68ebae62011-04-28 20:55:26 +0000130 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000131 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000132 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000133 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000134 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
135 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000136 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000137 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000138 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000139
Greg Clayton68ebae62011-04-28 20:55:26 +0000140 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000141 {
142 default:
143 break;
144
145 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000146 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000147 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000148 if (!num_per_line_option_set)
149 m_num_per_line = 1;
150 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000151 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000152 break;
153
154 case eFormatCString:
155 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000156
157 case eFormatInstruction:
158 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000159 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000160 m_num_per_line = 1;
161 break;
162
163 case eFormatAddressInfo:
164 if (!byte_size_option_set)
165 byte_size_value = target->GetArchitecture().GetAddressByteSize();
166 m_num_per_line = 1;
167 if (!count_option_set)
168 format_options.GetCountValue() = 8;
169 break;
170
Greg Clayton84c39662011-04-27 22:04:39 +0000171 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000172 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000173 if (!num_per_line_option_set)
174 m_num_per_line = 4;
175 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000176 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000177 break;
178
179 case eFormatBinary:
180 case eFormatFloat:
181 case eFormatOctal:
182 case eFormatDecimal:
183 case eFormatEnum:
184 case eFormatUnicode16:
185 case eFormatUnicode32:
186 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000187 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000188 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000189 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000190 if (!num_per_line_option_set)
191 m_num_per_line = 1;
192 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000193 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000194 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000195
Greg Clayton84c39662011-04-27 22:04:39 +0000196 case eFormatBytes:
197 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000198 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000199 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000200 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000201 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000202 "\tconsider using a different display format or don't specify the byte size",
203 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000204 }
205 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000206 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000207 if (!num_per_line_option_set)
208 m_num_per_line = 16;
209 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000210 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000211 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000212 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000213 case eFormatChar:
214 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000215 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000216 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000217 if (!num_per_line_option_set)
218 m_num_per_line = 32;
219 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000220 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000221 break;
222 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000223 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000224 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000225 if (!num_per_line_option_set)
226 m_num_per_line = 1;
227 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000228 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000229 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000230 case eFormatComplexInteger:
231 if (!byte_size_option_set)
232 byte_size_value = 8;
233 if (!num_per_line_option_set)
234 m_num_per_line = 1;
235 if (!count_option_set)
236 format_options.GetCountValue() = 8;
237 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000238 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000239 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000240 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000241 if (!num_per_line_option_set)
242 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000243 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000244 {
245 case 1:
246 case 2:
247 m_num_per_line = 8;
248 break;
249 case 4:
250 m_num_per_line = 4;
251 break;
252 case 8:
253 m_num_per_line = 2;
254 break;
255 default:
256 m_num_per_line = 1;
257 break;
258 }
259 }
260 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000261 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000262 break;
263
264 case eFormatVectorOfChar:
265 case eFormatVectorOfSInt8:
266 case eFormatVectorOfUInt8:
267 case eFormatVectorOfSInt16:
268 case eFormatVectorOfUInt16:
269 case eFormatVectorOfSInt32:
270 case eFormatVectorOfUInt32:
271 case eFormatVectorOfSInt64:
272 case eFormatVectorOfUInt64:
273 case eFormatVectorOfFloat32:
274 case eFormatVectorOfFloat64:
275 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000276 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000277 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000278 if (!num_per_line_option_set)
279 m_num_per_line = 1;
280 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000281 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000282 break;
283 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000284 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000285 }
286
Greg Clayton82f4cf42011-10-26 04:32:38 +0000287 bool
288 AnyOptionWasSet () const
289 {
290 return m_num_per_line.OptionWasSet() ||
291 m_output_as_binary ||
292 m_view_as_type.OptionWasSet();
293 }
294
Greg Clayton84c39662011-04-27 22:04:39 +0000295 OptionValueUInt64 m_num_per_line;
296 bool m_output_as_binary;
297 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000298 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000299};
300
301
302
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000303//----------------------------------------------------------------------
304// Read memory from the inferior process
305//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000306class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000307{
308public:
309
Greg Claytona7015092010-09-18 01:14:36 +0000310 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000311 CommandObjectParsed (interpreter,
312 "memory read",
313 "Read from the memory of the process being debugged.",
314 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000315 eFlagRequiresTarget | eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000316 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000317 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000318 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000319 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000320 m_varobj_options(),
321 m_next_addr(LLDB_INVALID_ADDRESS),
322 m_prev_byte_size(0),
323 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
324 m_prev_memory_options (),
325 m_prev_outfile_options (),
326 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000327 {
Caroline Tice405fe672010-10-04 22:28:36 +0000328 CommandArgumentEntry arg1;
329 CommandArgumentEntry arg2;
330 CommandArgumentData start_addr_arg;
331 CommandArgumentData end_addr_arg;
332
333 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000334 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000335 start_addr_arg.arg_repetition = eArgRepeatPlain;
336
337 // There is only one variant this argument could be; put it into the argument entry.
338 arg1.push_back (start_addr_arg);
339
340 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000341 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000342 end_addr_arg.arg_repetition = eArgRepeatOptional;
343
344 // There is only one variant this argument could be; put it into the argument entry.
345 arg2.push_back (end_addr_arg);
346
347 // Push the data for the first argument into the m_arguments vector.
348 m_arguments.push_back (arg1);
349 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000350
Greg Clayton1deb7962011-10-25 06:44:01 +0000351 // Add the "--format" and "--count" options to group 1 and 3
352 m_option_group.Append (&m_format_options,
353 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000354 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000355 m_option_group.Append (&m_format_options,
356 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000357 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000358 // Add the "--size" option to group 1 and 2
359 m_option_group.Append (&m_format_options,
360 OptionGroupFormat::OPTION_GROUP_SIZE,
361 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000362 m_option_group.Append (&m_memory_options);
363 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 +0000364 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000365 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000366 }
367
368 virtual
369 ~CommandObjectMemoryRead ()
370 {
371 }
372
373 Options *
374 GetOptions ()
375 {
Greg Clayton84c39662011-04-27 22:04:39 +0000376 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000377 }
378
Greg Clayton82f4cf42011-10-26 04:32:38 +0000379 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
380 {
381 return m_cmd_name.c_str();
382 }
383
Jim Ingham5a988412012-06-08 21:56:10 +0000384protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000386 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000388 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
389 Target *target = m_exe_ctx.GetTargetPtr();
390
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000391 const size_t argc = command.GetArgumentCount();
392
Greg Clayton82f4cf42011-10-26 04:32:38 +0000393 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000394 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000395 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 +0000396 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397 result.SetStatus(eReturnStatusFailed);
398 return false;
399 }
400
Greg Clayton68ebae62011-04-28 20:55:26 +0000401 ClangASTType clang_ast_type;
402 Error error;
403
Greg Clayton84c39662011-04-27 22:04:39 +0000404 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
405 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000406 {
Greg Clayton84c39662011-04-27 22:04:39 +0000407 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000408
Greg Clayton84c39662011-04-27 22:04:39 +0000409 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000410 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000411 TypeList type_list;
412 uint32_t reference_count = 0;
413 uint32_t pointer_count = 0;
414 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000415
416#define ALL_KEYWORDS \
417 KEYWORD("const") \
418 KEYWORD("volatile") \
419 KEYWORD("restrict") \
420 KEYWORD("struct") \
421 KEYWORD("class") \
422 KEYWORD("union")
423
424#define KEYWORD(s) s,
425 static const char *g_keywords[] =
426 {
427 ALL_KEYWORDS
428 };
429#undef KEYWORD
430
431#define KEYWORD(s) (sizeof(s) - 1),
432 static const int g_keyword_lengths[] =
433 {
434 ALL_KEYWORDS
435 };
436#undef KEYWORD
437
438#undef ALL_KEYWORDS
439
440 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000441 std::string type_str(view_as_type_cstr);
442
443 // Remove all instances of g_keywords that are followed by spaces
444 for (size_t i = 0; i < g_num_keywords; ++i)
445 {
446 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000447 int keyword_len = g_keyword_lengths[i];
448
449 idx = 0;
450 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000451 {
452 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000453 {
Greg Clayton84c39662011-04-27 22:04:39 +0000454 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000455 idx = 0;
456 }
457 else
458 {
459 idx += keyword_len;
460 }
Greg Clayton84c39662011-04-27 22:04:39 +0000461 }
462 }
463 bool done = type_str.empty();
464 //
465 idx = type_str.find_first_not_of (" \t");
466 if (idx > 0 && idx != std::string::npos)
467 type_str.erase (0, idx);
468 while (!done)
469 {
470 // Strip trailing spaces
471 if (type_str.empty())
472 done = true;
473 else
474 {
475 switch (type_str[type_str.size()-1])
476 {
477 case '*':
478 ++pointer_count;
479 // fall through...
480 case ' ':
481 case '\t':
482 type_str.erase(type_str.size()-1);
483 break;
484
485 case '&':
486 if (reference_count == 0)
487 {
488 reference_count = 1;
489 type_str.erase(type_str.size()-1);
490 }
491 else
492 {
493 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
494 result.SetStatus(eReturnStatusFailed);
495 return false;
496 }
497 break;
498
499 default:
500 done = true;
501 break;
502 }
503 }
504 }
505
506 ConstString lookup_type_name(type_str.c_str());
Jason Molendab57e4a12013-11-04 09:33:30 +0000507 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000508 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000509 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000510 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000511 if (sc.module_sp)
512 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000513 sc.module_sp->FindTypes (sc,
514 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000515 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000516 1,
517 type_list);
518 }
519 }
520 if (type_list.GetSize() == 0)
521 {
Greg Clayton29399a22012-04-06 17:41:13 +0000522 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000523 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000524 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000525 1,
526 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000527 }
528
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000529 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000530 {
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000531 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
532 if (tdecl)
533 {
534 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
535 }
Greg Clayton84c39662011-04-27 22:04:39 +0000536 }
537
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000538 if (clang_ast_type.IsValid() == false)
539 {
540 if (type_list.GetSize() == 0)
541 {
542 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
543 lookup_type_name.GetCString(),
544 view_as_type_cstr);
545 result.SetStatus(eReturnStatusFailed);
546 return false;
547 }
548 else
549 {
550 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton57ee3062013-07-11 22:46:58 +0000551 clang_ast_type = type_sp->GetClangFullType();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000552 }
553 }
Greg Clayton84c39662011-04-27 22:04:39 +0000554
555 while (pointer_count > 0)
556 {
Greg Clayton57ee3062013-07-11 22:46:58 +0000557 ClangASTType pointer_type = clang_ast_type.GetPointerType();
558 if (pointer_type.IsValid())
559 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000560 else
561 {
562 result.AppendError ("unable make a pointer type\n");
563 result.SetStatus(eReturnStatusFailed);
564 return false;
565 }
566 --pointer_count;
567 }
568
Greg Clayton57ee3062013-07-11 22:46:58 +0000569 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize();
Greg Clayton84c39662011-04-27 22:04:39 +0000570
Greg Clayton1deb7962011-10-25 06:44:01 +0000571 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000572 {
573 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
574 view_as_type_cstr);
575 result.SetStatus(eReturnStatusFailed);
576 return false;
577 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000578
Greg Clayton1deb7962011-10-25 06:44:01 +0000579 if (!m_format_options.GetCountValue().OptionWasSet())
580 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000581 }
582 else
583 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000584 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000585 }
586
587 // Look for invalid combinations of settings
588 if (error.Fail())
589 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000590 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000591 result.SetStatus(eReturnStatusFailed);
592 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000593 }
594
Greg Clayton82f4cf42011-10-26 04:32:38 +0000595 lldb::addr_t addr;
596 size_t total_byte_size = 0;
597 if (argc == 0)
598 {
599 // Use the last address and byte size and all options as they were
600 // if no options have been set
601 addr = m_next_addr;
602 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000603 clang_ast_type = m_prev_clang_ast_type;
604 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000605 !m_memory_options.AnyOptionWasSet() &&
606 !m_outfile_options.AnyOptionWasSet() &&
607 !m_varobj_options.AnyOptionWasSet())
608 {
609 m_format_options = m_prev_format_options;
610 m_memory_options = m_prev_memory_options;
611 m_outfile_options = m_prev_outfile_options;
612 m_varobj_options = m_prev_varobj_options;
613 }
614 }
615
Greg Clayton1deb7962011-10-25 06:44:01 +0000616 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000617 size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton68ebae62011-04-28 20:55:26 +0000618 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000619
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000620 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000621 {
622 total_byte_size = item_count * item_byte_size;
623 if (total_byte_size == 0)
624 total_byte_size = 32;
625 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000626
Greg Clayton82f4cf42011-10-26 04:32:38 +0000627 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000628 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000629
630 if (addr == LLDB_INVALID_ADDRESS)
631 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000632 result.AppendError("invalid start address expression.");
633 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000634 result.SetStatus(eReturnStatusFailed);
635 return false;
636 }
637
638 if (argc == 2)
639 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000640 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000641 if (end_addr == LLDB_INVALID_ADDRESS)
642 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000643 result.AppendError("invalid end address expression.");
644 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000645 result.SetStatus(eReturnStatusFailed);
646 return false;
647 }
648 else if (end_addr <= addr)
649 {
Daniel Malead01b2952012-11-29 21:49:15 +0000650 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 +0000651 result.SetStatus(eReturnStatusFailed);
652 return false;
653 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000654 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000655 {
Greg Clayton6fea17e2014-03-03 19:15:20 +0000656 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 +0000657 result.SetStatus(eReturnStatusFailed);
658 return false;
659 }
660
661 total_byte_size = end_addr - addr;
662 item_count = total_byte_size / item_byte_size;
663 }
Greg Clayton84c39662011-04-27 22:04:39 +0000664
Enrico Granatad325bf92013-06-04 22:54:16 +0000665 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
666
667 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000668 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000669 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
670 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
671 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 +0000672 return false;
673 }
674
Greg Clayton84c39662011-04-27 22:04:39 +0000675 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000676 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000677 if (clang_ast_type.GetOpaqueQualType())
678 {
679 // Make sure we don't display our type as ASCII bytes like the default memory read
680 if (m_format_options.GetFormatValue().OptionWasSet() == false)
681 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
682
Greg Clayton57ee3062013-07-11 22:46:58 +0000683 bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000684 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000685 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000686 {
Greg Clayton84c39662011-04-27 22:04:39 +0000687 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000688 if (data_sp->GetBytes() == NULL)
689 {
Virgile Belloffeba252014-03-08 17:15:35 +0000690 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 +0000691 result.SetStatus(eReturnStatusFailed);
692 return false;
693 }
694
Greg Claytone72dfb32012-02-24 01:59:29 +0000695 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000696 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000697 if (bytes_read == 0)
698 {
Greg Clayton57f06302012-05-25 17:05:55 +0000699 const char *error_cstr = error.AsCString();
700 if (error_cstr && error_cstr[0])
701 {
702 result.AppendError(error_cstr);
703 }
704 else
705 {
Daniel Malead01b2952012-11-29 21:49:15 +0000706 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000707 }
Greg Clayton84c39662011-04-27 22:04:39 +0000708 result.SetStatus(eReturnStatusFailed);
709 return false;
710 }
711
712 if (bytes_read < total_byte_size)
Greg Clayton6fea17e2014-03-03 19:15:20 +0000713 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 +0000714 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000715 else
716 {
717 // we treat c-strings as a special case because they do not have a fixed size
718 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
719 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
720 else
721 item_byte_size = target->GetMaximumSizeOfStringSummary();
722 if (!m_format_options.GetCountValue().OptionWasSet())
723 item_count = 1;
724 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000725 if (data_sp->GetBytes() == NULL)
726 {
727 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));
728 result.SetStatus(eReturnStatusFailed);
729 return false;
730 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000731 uint8_t *data_ptr = data_sp->GetBytes();
732 auto data_addr = addr;
733 auto count = item_count;
734 item_count = 0;
735 while (item_count < count)
736 {
737 std::string buffer;
738 buffer.resize(item_byte_size+1,0);
739 Error error;
740 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
741 if (error.Fail())
742 {
743 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
744 result.SetStatus(eReturnStatusFailed);
745 return false;
746 }
747 if (item_byte_size == read)
748 {
749 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
750 break;
751 }
752 read+=1; // account for final NULL byte
753 memcpy(data_ptr, &buffer[0], read);
754 data_ptr += read;
755 data_addr += read;
756 bytes_read += read;
757 item_count++; // if we break early we know we only read item_count strings
758 }
759 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
760 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000761
Greg Clayton2e1f7452012-12-15 02:08:17 +0000762 m_next_addr = addr + bytes_read;
763 m_prev_byte_size = bytes_read;
764 m_prev_format_options = m_format_options;
765 m_prev_memory_options = m_memory_options;
766 m_prev_outfile_options = m_outfile_options;
767 m_prev_varobj_options = m_varobj_options;
768 m_prev_clang_ast_type = clang_ast_type;
769
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000770 StreamFile outfile_stream;
771 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000772 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
773 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000774 {
775 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000776 outfile_spec.GetPath (path, sizeof(path));
777
778 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
779 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
780 if (append)
781 open_options |= File::eOpenOptionAppend;
782
783 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000784 {
Greg Clayton84c39662011-04-27 22:04:39 +0000785 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000786 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000787 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000788 if (bytes_written > 0)
789 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000790 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000791 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000792 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000793 path);
794 return true;
795 }
796 else
797 {
Daniel Malead01b2952012-11-29 21:49:15 +0000798 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000799 result.SetStatus(eReturnStatusFailed);
800 return false;
801 }
802 }
803 else
804 {
805 // We are going to write ASCII to the file just point the
806 // output_stream to our outfile_stream...
807 output_stream = &outfile_stream;
808 }
809 }
810 else
811 {
Greg Clayton84c39662011-04-27 22:04:39 +0000812 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000813 result.SetStatus(eReturnStatusFailed);
814 return false;
815 }
816 }
817 else
818 {
819 output_stream = &result.GetOutputStream();
820 }
821
Greg Clayton84c39662011-04-27 22:04:39 +0000822
Greg Claytonf9fc6092013-01-09 19:44:40 +0000823 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000824 if (clang_ast_type.GetOpaqueQualType())
825 {
826 for (uint32_t i = 0; i<item_count; ++i)
827 {
828 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000829 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000830 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000831 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000832 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000833 name_strm.GetString().c_str(),
834 address,
835 clang_ast_type));
836 if (valobj_sp)
837 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000838 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000839 if (format != eFormatDefault)
840 valobj_sp->SetFormat (format);
841
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000842 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000843
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000844 valobj_sp->Dump(*output_stream,options);
Greg Clayton84c39662011-04-27 22:04:39 +0000845 }
846 else
847 {
848 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
849 view_as_type_cstr,
850 name_strm.GetString().c_str());
851 result.SetStatus(eReturnStatusFailed);
852 return false;
853 }
854 }
855 return true;
856 }
857
858 result.SetStatus(eReturnStatusSuccessFinishResult);
859 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000860 target->GetArchitecture().GetByteOrder(),
861 target->GetArchitecture().GetAddressByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000862
863 Format format = m_format_options.GetFormat();
864 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
Enrico Granata0947a6e2013-10-29 23:04:29 +0000865 && (item_byte_size != 1))
Enrico Granata31898912013-05-21 17:39:04 +0000866 {
Enrico Granata0947a6e2013-10-29 23:04:29 +0000867 // if a count was not passed, or it is 1
868 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
869 {
870 // this turns requests such as
871 // memory read -fc -s10 -c1 *charPtrPtr
872 // which make no sense (what is a char of size 10?)
873 // into a request for fetching 10 chars of size 1 from the same memory location
874 format = eFormatCharArray;
875 item_count = item_byte_size;
876 item_byte_size = 1;
877 }
878 else
879 {
880 // here we passed a count, and it was not 1
881 // so we have a byte_size and a count
882 // we could well multiply those, but instead let's just fail
Greg Clayton6fea17e2014-03-03 19:15:20 +0000883 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
Enrico Granata0947a6e2013-10-29 23:04:29 +0000884 result.SetStatus(eReturnStatusFailed);
885 return false;
886 }
Enrico Granata31898912013-05-21 17:39:04 +0000887 }
Greg Clayton84c39662011-04-27 22:04:39 +0000888
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000889 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000890 size_t bytes_dumped = data.Dump (output_stream,
891 0,
Enrico Granata31898912013-05-21 17:39:04 +0000892 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000893 item_byte_size,
894 item_count,
895 num_per_line,
896 addr,
897 0,
898 0,
899 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000900 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000901 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000902 return true;
903 }
904
Greg Clayton84c39662011-04-27 22:04:39 +0000905 OptionGroupOptions m_option_group;
906 OptionGroupFormat m_format_options;
907 OptionGroupReadMemory m_memory_options;
908 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000909 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000910 lldb::addr_t m_next_addr;
911 lldb::addr_t m_prev_byte_size;
912 OptionGroupFormat m_prev_format_options;
913 OptionGroupReadMemory m_prev_memory_options;
914 OptionGroupOutputFile m_prev_outfile_options;
915 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000916 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000917};
918
Enrico Granata53468432013-11-13 02:18:44 +0000919OptionDefinition
920g_memory_find_option_table[] =
921{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000922 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
923 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
924 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."},
925 { 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 +0000926};
927
Enrico Granata53468432013-11-13 02:18:44 +0000928//----------------------------------------------------------------------
929// Find the specified data in memory
930//----------------------------------------------------------------------
931class CommandObjectMemoryFind : public CommandObjectParsed
932{
933public:
934
935 class OptionGroupFindMemory : public OptionGroup
936 {
937 public:
938 OptionGroupFindMemory () :
939 OptionGroup(),
940 m_count(1),
Enrico Granata8d81a842013-11-13 20:08:30 +0000941 m_offset(0)
Enrico Granata53468432013-11-13 02:18:44 +0000942 {
943 }
944
945 virtual
946 ~OptionGroupFindMemory ()
947 {
948 }
949
950 virtual uint32_t
951 GetNumDefinitions ()
952 {
953 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
954 }
955
956 virtual const OptionDefinition*
957 GetDefinitions ()
958 {
959 return g_memory_find_option_table;
960 }
961
962 virtual Error
963 SetOptionValue (CommandInterpreter &interpreter,
964 uint32_t option_idx,
965 const char *option_arg)
966 {
967 Error error;
968 const int short_option = g_memory_find_option_table[option_idx].short_option;
969
970 switch (short_option)
971 {
972 case 'e':
973 m_expr.SetValueFromCString(option_arg);
974 break;
975
976 case 's':
977 m_string.SetValueFromCString(option_arg);
978 break;
979
980 case 'c':
981 if (m_count.SetValueFromCString(option_arg).Fail())
982 error.SetErrorString("unrecognized value for count");
983 break;
984
Enrico Granata8d81a842013-11-13 20:08:30 +0000985 case 'o':
986 if (m_offset.SetValueFromCString(option_arg).Fail())
987 error.SetErrorString("unrecognized value for dump-offset");
988 break;
989
Enrico Granata53468432013-11-13 02:18:44 +0000990 default:
991 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
992 break;
993 }
994 return error;
995 }
996
997 virtual void
998 OptionParsingStarting (CommandInterpreter &interpreter)
999 {
1000 m_expr.Clear();
1001 m_string.Clear();
1002 m_count.Clear();
Enrico Granata53468432013-11-13 02:18:44 +00001003 }
1004
1005 OptionValueString m_expr;
1006 OptionValueString m_string;
1007 OptionValueUInt64 m_count;
Enrico Granata8d81a842013-11-13 20:08:30 +00001008 OptionValueUInt64 m_offset;
Enrico Granata53468432013-11-13 02:18:44 +00001009 };
1010
1011 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1012 CommandObjectParsed (interpreter,
1013 "memory find",
1014 "Find a value in the memory of the process being debugged.",
1015 NULL,
1016 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
1017 m_option_group (interpreter),
1018 m_memory_options ()
1019 {
1020 CommandArgumentEntry arg1;
1021 CommandArgumentEntry arg2;
1022 CommandArgumentData addr_arg;
1023 CommandArgumentData value_arg;
1024
1025 // Define the first (and only) variant of this arg.
1026 addr_arg.arg_type = eArgTypeAddress;
1027 addr_arg.arg_repetition = eArgRepeatPlain;
1028
1029 // There is only one variant this argument could be; put it into the argument entry.
1030 arg1.push_back (addr_arg);
1031
1032 // Define the first (and only) variant of this arg.
1033 value_arg.arg_type = eArgTypeValue;
1034 value_arg.arg_repetition = eArgRepeatPlus;
1035
1036 // There is only one variant this argument could be; put it into the argument entry.
1037 arg2.push_back (value_arg);
1038
1039 // Push the data for the first argument into the m_arguments vector.
1040 m_arguments.push_back (arg1);
1041 m_arguments.push_back (arg2);
1042
1043 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1044 m_option_group.Finalize();
1045 }
1046
1047 virtual
1048 ~CommandObjectMemoryFind ()
1049 {
1050 }
1051
1052 Options *
1053 GetOptions ()
1054 {
1055 return &m_option_group;
1056 }
1057
1058protected:
1059 virtual bool
1060 DoExecute (Args& command, CommandReturnObject &result)
1061 {
1062 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1063 Process *process = m_exe_ctx.GetProcessPtr();
1064
1065 const size_t argc = command.GetArgumentCount();
1066
1067 if (argc != 2)
1068 {
Enrico Granata6e49c482013-11-13 02:22:24 +00001069 result.AppendError("two addresses needed for memory find");
Enrico Granata53468432013-11-13 02:18:44 +00001070 return false;
1071 }
1072
1073 Error error;
1074 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1075 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1076 {
1077 result.AppendError("invalid low address");
1078 return false;
1079 }
1080 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1081 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1082 {
Ed Maste47a8a5e2014-09-06 11:29:08 +00001083 result.AppendError("invalid high address");
Enrico Granata53468432013-11-13 02:18:44 +00001084 return false;
1085 }
1086
1087 if (high_addr <= low_addr)
1088 {
1089 result.AppendError("starting address must be smaller than ending address");
1090 return false;
1091 }
1092
1093 lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1094
1095 DataBufferHeap buffer;
1096
1097 if (m_memory_options.m_string.OptionWasSet())
1098 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1099 else if (m_memory_options.m_expr.OptionWasSet())
1100 {
1101 StackFrame* frame = m_exe_ctx.GetFramePtr();
1102 ValueObjectSP result_sp;
1103 if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
1104 {
1105 uint64_t value = result_sp->GetValueAsUnsigned(0);
1106 switch (result_sp->GetClangType().GetByteSize())
1107 {
1108 case 1: {
1109 uint8_t byte = (uint8_t)value;
1110 buffer.CopyData(&byte,1);
1111 }
1112 break;
1113 case 2: {
1114 uint16_t word = (uint16_t)value;
1115 buffer.CopyData(&word,2);
1116 }
1117 break;
1118 case 4: {
1119 uint32_t lword = (uint32_t)value;
1120 buffer.CopyData(&lword,4);
1121 }
1122 break;
1123 case 8: {
1124 buffer.CopyData(&value, 8);
1125 }
1126 break;
1127 case 3:
1128 case 5:
1129 case 6:
1130 case 7:
1131 result.AppendError("unknown type. pass a string instead");
1132 return false;
1133 default:
1134 result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
1135 return false;
1136 }
1137 }
1138 else
1139 {
1140 result.AppendError("expression evaluation failed. pass a string instead?");
1141 return false;
1142 }
1143 }
1144 else
1145 {
1146 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1147 return false;
1148 }
1149
1150 size_t count = m_memory_options.m_count.GetCurrentValue();
1151 found_location = low_addr;
1152 bool ever_found = false;
1153 while (count)
1154 {
1155 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1156 if (found_location == LLDB_INVALID_ADDRESS)
1157 {
1158 if (!ever_found)
1159 {
1160 result.AppendMessage("Your data was not found within the range.\n");
1161 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1162 }
1163 else
1164 result.AppendMessage("No more matches found within the range.\n");
1165 break;
1166 }
1167 result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
Enrico Granata8d81a842013-11-13 20:08:30 +00001168
1169 DataBufferHeap dumpbuffer(32,0);
1170 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1171 if (!error.Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001172 {
Enrico Granata8d81a842013-11-13 20:08:30 +00001173 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1174 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1175 result.GetOutputStream().EOL();
Enrico Granata53468432013-11-13 02:18:44 +00001176 }
Enrico Granata8d81a842013-11-13 20:08:30 +00001177
Enrico Granata53468432013-11-13 02:18:44 +00001178 --count;
1179 found_location++;
1180 ever_found = true;
1181 }
1182
1183 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1184 return true;
1185 }
1186
1187 lldb::addr_t
1188 Search (lldb::addr_t low,
1189 lldb::addr_t high,
1190 uint8_t* buffer,
1191 size_t buffer_size)
1192 {
1193 Process *process = m_exe_ctx.GetProcessPtr();
1194 DataBufferHeap heap(buffer_size, 0);
1195 lldb::addr_t fictional_ptr = low;
1196 for (auto ptr = low;
1197 low < high;
1198 fictional_ptr++)
1199 {
1200 Error error;
1201 if (ptr == low || buffer_size == 1)
1202 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1203 else
1204 {
1205 memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
1206 process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
1207 }
1208 if (error.Fail())
1209 return LLDB_INVALID_ADDRESS;
1210 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1211 return fictional_ptr;
1212 if (ptr == low)
1213 ptr += buffer_size;
1214 else
1215 ptr += 1;
1216 }
1217 return LLDB_INVALID_ADDRESS;
1218 }
1219
1220 OptionGroupOptions m_option_group;
1221 OptionGroupFindMemory m_memory_options;
1222};
1223
Greg Clayton1deb7962011-10-25 06:44:01 +00001224
1225OptionDefinition
1226g_memory_write_option_table[] =
1227{
Zachary Turnerd37221d2014-07-09 16:31:49 +00001228{ 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 +00001229{ 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 +00001230};
1231
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001232//----------------------------------------------------------------------
1233// Write memory to the inferior process
1234//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001235class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001236{
1237public:
1238
Greg Clayton1deb7962011-10-25 06:44:01 +00001239 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001240 {
1241 public:
Greg Clayton1deb7962011-10-25 06:44:01 +00001242 OptionGroupWriteMemory () :
1243 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001244 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001245 }
1246
1247 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +00001248 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001249 {
1250 }
1251
Greg Clayton1deb7962011-10-25 06:44:01 +00001252 virtual uint32_t
1253 GetNumDefinitions ()
1254 {
1255 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1256 }
Enrico Granata53468432013-11-13 02:18:44 +00001257
Greg Clayton1deb7962011-10-25 06:44:01 +00001258 virtual const OptionDefinition*
1259 GetDefinitions ()
1260 {
1261 return g_memory_write_option_table;
1262 }
Enrico Granata53468432013-11-13 02:18:44 +00001263
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001264 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +00001265 SetOptionValue (CommandInterpreter &interpreter,
1266 uint32_t option_idx,
1267 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001268 {
1269 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001270 const int short_option = g_memory_write_option_table[option_idx].short_option;
Enrico Granata53468432013-11-13 02:18:44 +00001271
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001272 switch (short_option)
1273 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001274 case 'i':
1275 m_infile.SetFile (option_arg, true);
1276 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001277 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001278 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +00001279 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001280 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001281 break;
Enrico Granata53468432013-11-13 02:18:44 +00001282
Greg Clayton1deb7962011-10-25 06:44:01 +00001283 case 'o':
1284 {
1285 bool success;
1286 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
1287 if (!success)
1288 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001289 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +00001290 }
1291 }
1292 break;
1293
1294 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001295 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +00001296 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001297 }
1298 return error;
1299 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001300
1301 virtual void
1302 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001303 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001304 m_infile.Clear();
1305 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001306 }
1307
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001308 FileSpec m_infile;
1309 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001310 };
1311
Greg Claytona7015092010-09-18 01:14:36 +00001312 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001313 CommandObjectParsed (interpreter,
1314 "memory write",
1315 "Write to the memory of the process being debugged.",
1316 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +00001317 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001318 m_option_group (interpreter),
1319 m_format_options (eFormatBytes, 1, UINT64_MAX),
1320 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001321 {
Caroline Tice405fe672010-10-04 22:28:36 +00001322 CommandArgumentEntry arg1;
1323 CommandArgumentEntry arg2;
1324 CommandArgumentData addr_arg;
1325 CommandArgumentData value_arg;
1326
1327 // Define the first (and only) variant of this arg.
1328 addr_arg.arg_type = eArgTypeAddress;
1329 addr_arg.arg_repetition = eArgRepeatPlain;
1330
1331 // There is only one variant this argument could be; put it into the argument entry.
1332 arg1.push_back (addr_arg);
1333
1334 // Define the first (and only) variant of this arg.
1335 value_arg.arg_type = eArgTypeValue;
1336 value_arg.arg_repetition = eArgRepeatPlus;
1337
1338 // There is only one variant this argument could be; put it into the argument entry.
1339 arg2.push_back (value_arg);
1340
1341 // Push the data for the first argument into the m_arguments vector.
1342 m_arguments.push_back (arg1);
1343 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001344
1345 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1346 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1347 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1348 m_option_group.Finalize();
1349
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001350 }
1351
1352 virtual
1353 ~CommandObjectMemoryWrite ()
1354 {
1355 }
1356
1357 Options *
1358 GetOptions ()
1359 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001360 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001361 }
1362
1363 bool
1364 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1365 {
1366 if (total_byte_size > 8)
1367 return false;
1368
1369 if (total_byte_size == 8)
1370 return true;
1371
1372 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1373 return uval64 <= max;
1374 }
1375
1376 bool
1377 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1378 {
1379 if (total_byte_size > 8)
1380 return false;
1381
1382 if (total_byte_size == 8)
1383 return true;
1384
1385 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1386 const int64_t min = ~(max);
1387 return min <= sval64 && sval64 <= max;
1388 }
1389
Jim Ingham5a988412012-06-08 21:56:10 +00001390protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001391 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001392 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001393 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001394 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1395 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001396
1397 const size_t argc = command.GetArgumentCount();
1398
Greg Clayton1deb7962011-10-25 06:44:01 +00001399 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001400 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001401 if (argc < 1)
1402 {
1403 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1404 result.SetStatus(eReturnStatusFailed);
1405 return false;
1406 }
1407 }
1408 else if (argc < 2)
1409 {
1410 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 +00001411 result.SetStatus(eReturnStatusFailed);
1412 return false;
1413 }
1414
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001415 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001416 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1417 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001418
Greg Clayton1deb7962011-10-25 06:44:01 +00001419 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1420 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001421
Greg Claytonb9d5df52012-12-06 22:49:16 +00001422 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001423 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001424 command.GetArgumentAtIndex(0),
1425 LLDB_INVALID_ADDRESS,
1426 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001427
1428 if (addr == LLDB_INVALID_ADDRESS)
1429 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001430 result.AppendError("invalid address expression\n");
1431 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001432 result.SetStatus(eReturnStatusFailed);
1433 return false;
1434 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001435
Greg Clayton1deb7962011-10-25 06:44:01 +00001436 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001437 {
1438 size_t length = SIZE_MAX;
Greg Clayton1deb7962011-10-25 06:44:01 +00001439 if (item_byte_size > 0)
1440 length = item_byte_size;
1441 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001442 if (data_sp)
1443 {
1444 length = data_sp->GetByteSize();
1445 if (length > 0)
1446 {
1447 Error error;
1448 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1449
1450 if (bytes_written == length)
1451 {
1452 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001453 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001454 result.SetStatus(eReturnStatusSuccessFinishResult);
1455 }
1456 else if (bytes_written > 0)
1457 {
1458 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001459 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 +00001460 result.SetStatus(eReturnStatusSuccessFinishResult);
1461 }
1462 else
1463 {
Daniel Malead01b2952012-11-29 21:49:15 +00001464 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001465 result.SetStatus(eReturnStatusFailed);
1466 }
1467 }
1468 }
1469 else
1470 {
1471 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1472 result.SetStatus(eReturnStatusFailed);
1473 }
1474 return result.Succeeded();
1475 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001476 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001477 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001478 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001479 item_byte_size = buffer.GetAddressByteSize();
1480 else
1481 item_byte_size = 1;
1482 }
1483
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001484 command.Shift(); // shift off the address argument
1485 uint64_t uval64;
1486 int64_t sval64;
1487 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001488 const size_t num_value_args = command.GetArgumentCount();
1489 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001490 {
1491 const char *value_str = command.GetArgumentAtIndex(i);
1492
Greg Clayton1deb7962011-10-25 06:44:01 +00001493 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001494 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001495 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001496 case eFormatFloat: // TODO: add support for floats soon
1497 case eFormatCharPrintable:
1498 case eFormatBytesWithASCII:
1499 case eFormatComplex:
1500 case eFormatEnum:
1501 case eFormatUnicode16:
1502 case eFormatUnicode32:
1503 case eFormatVectorOfChar:
1504 case eFormatVectorOfSInt8:
1505 case eFormatVectorOfUInt8:
1506 case eFormatVectorOfSInt16:
1507 case eFormatVectorOfUInt16:
1508 case eFormatVectorOfSInt32:
1509 case eFormatVectorOfUInt32:
1510 case eFormatVectorOfSInt64:
1511 case eFormatVectorOfUInt64:
1512 case eFormatVectorOfFloat32:
1513 case eFormatVectorOfFloat64:
1514 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001515 case eFormatOSType:
1516 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001517 case eFormatAddressInfo:
1518 case eFormatHexFloat:
1519 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001520 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001521 result.AppendError("unsupported format for writing memory");
1522 result.SetStatus(eReturnStatusFailed);
1523 return false;
1524
1525 case eFormatDefault:
1526 case eFormatBytes:
1527 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001528 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001529 case eFormatPointer:
1530
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001531 // Decode hex bytes
1532 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1533 if (!success)
1534 {
1535 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1536 result.SetStatus(eReturnStatusFailed);
1537 return false;
1538 }
1539 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1540 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001541 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 +00001542 result.SetStatus(eReturnStatusFailed);
1543 return false;
1544 }
1545 buffer.PutMaxHex64 (uval64, item_byte_size);
1546 break;
1547
1548 case eFormatBoolean:
1549 uval64 = Args::StringToBoolean(value_str, false, &success);
1550 if (!success)
1551 {
1552 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1553 result.SetStatus(eReturnStatusFailed);
1554 return false;
1555 }
1556 buffer.PutMaxHex64 (uval64, item_byte_size);
1557 break;
1558
1559 case eFormatBinary:
1560 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1561 if (!success)
1562 {
1563 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1564 result.SetStatus(eReturnStatusFailed);
1565 return false;
1566 }
1567 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1568 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001569 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 +00001570 result.SetStatus(eReturnStatusFailed);
1571 return false;
1572 }
1573 buffer.PutMaxHex64 (uval64, item_byte_size);
1574 break;
1575
Greg Clayton4e4294b2011-06-17 23:50:44 +00001576 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001577 case eFormatChar:
1578 case eFormatCString:
1579 if (value_str[0])
1580 {
1581 size_t len = strlen (value_str);
1582 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001583 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001584 ++len;
1585 Error error;
1586 if (process->WriteMemory (addr, value_str, len, error) == len)
1587 {
1588 addr += len;
1589 }
1590 else
1591 {
Daniel Malead01b2952012-11-29 21:49:15 +00001592 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001593 result.SetStatus(eReturnStatusFailed);
1594 return false;
1595 }
1596 }
1597 break;
1598
1599 case eFormatDecimal:
1600 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1601 if (!success)
1602 {
1603 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1604 result.SetStatus(eReturnStatusFailed);
1605 return false;
1606 }
1607 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1608 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001609 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 +00001610 result.SetStatus(eReturnStatusFailed);
1611 return false;
1612 }
1613 buffer.PutMaxHex64 (sval64, item_byte_size);
1614 break;
1615
1616 case eFormatUnsigned:
1617 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1618 if (!success)
1619 {
1620 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1621 result.SetStatus(eReturnStatusFailed);
1622 return false;
1623 }
1624 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1625 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001626 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 +00001627 result.SetStatus(eReturnStatusFailed);
1628 return false;
1629 }
1630 buffer.PutMaxHex64 (uval64, item_byte_size);
1631 break;
1632
1633 case eFormatOctal:
1634 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1635 if (!success)
1636 {
1637 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1638 result.SetStatus(eReturnStatusFailed);
1639 return false;
1640 }
1641 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1642 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001643 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 +00001644 result.SetStatus(eReturnStatusFailed);
1645 return false;
1646 }
1647 buffer.PutMaxHex64 (uval64, item_byte_size);
1648 break;
1649 }
1650 }
1651
1652 if (!buffer.GetString().empty())
1653 {
1654 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001655 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001656 return true;
1657 else
1658 {
Daniel Malead01b2952012-11-29 21:49:15 +00001659 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001660 result.SetStatus(eReturnStatusFailed);
1661 return false;
1662 }
1663 }
1664 return true;
1665 }
1666
Greg Clayton1deb7962011-10-25 06:44:01 +00001667 OptionGroupOptions m_option_group;
1668 OptionGroupFormat m_format_options;
1669 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001670};
1671
Kuba Breckabeed8212014-09-04 01:03:18 +00001672//----------------------------------------------------------------------
1673// Get malloc/free history of a memory address.
1674//----------------------------------------------------------------------
1675class CommandObjectMemoryHistory : public CommandObjectParsed
1676{
1677public:
1678
1679 CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1680 CommandObjectParsed (interpreter,
1681 "memory history",
1682 "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1683 NULL,
1684 eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched)
1685 {
1686 CommandArgumentEntry arg1;
1687 CommandArgumentData addr_arg;
1688
1689 // Define the first (and only) variant of this arg.
1690 addr_arg.arg_type = eArgTypeAddress;
1691 addr_arg.arg_repetition = eArgRepeatPlain;
1692
1693 // There is only one variant this argument could be; put it into the argument entry.
1694 arg1.push_back (addr_arg);
1695
1696 // Push the data for the first argument into the m_arguments vector.
1697 m_arguments.push_back (arg1);
1698 }
1699
1700 virtual
1701 ~CommandObjectMemoryHistory ()
1702 {
1703 }
1704
1705 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
1706 {
1707 return m_cmd_name.c_str();
1708 }
1709
1710protected:
1711 virtual bool
1712 DoExecute (Args& command, CommandReturnObject &result)
1713 {
1714 const size_t argc = command.GetArgumentCount();
1715
1716 if (argc == 0 || argc > 1)
1717 {
1718 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1719 result.SetStatus(eReturnStatusFailed);
1720 return false;
1721 }
1722
1723 Error error;
1724 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1725 command.GetArgumentAtIndex(0),
1726 LLDB_INVALID_ADDRESS,
1727 &error);
1728
1729 if (addr == LLDB_INVALID_ADDRESS)
1730 {
1731 result.AppendError("invalid address expression");
1732 result.AppendError(error.AsCString());
1733 result.SetStatus(eReturnStatusFailed);
1734 return false;
1735 }
1736
1737 Stream *output_stream = &result.GetOutputStream();
1738
1739 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1740 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1741
1742 if (! memory_history.get())
1743 {
1744 result.AppendError("no available memory history provider");
1745 result.SetStatus(eReturnStatusFailed);
1746 return false;
1747 }
1748
1749 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1750
1751 for (auto thread : thread_list) {
1752 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1753 }
1754
1755 result.SetStatus(eReturnStatusSuccessFinishResult);
1756
1757 return true;
1758 }
1759
1760};
1761
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001762
1763//-------------------------------------------------------------------------
1764// CommandObjectMemory
1765//-------------------------------------------------------------------------
1766
Greg Clayton66111032010-06-23 01:19:29 +00001767CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001768 CommandObjectMultiword (interpreter,
1769 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001770 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001771 "memory <subcommand> [<subcommand-options>]")
1772{
Enrico Granata53468432013-11-13 02:18:44 +00001773 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001774 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1775 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Kuba Breckabeed8212014-09-04 01:03:18 +00001776 LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001777}
1778
1779CommandObjectMemory::~CommandObjectMemory ()
1780{
1781}