1 //===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/lldb-python.h"
12 #include "CommandObjectMemory.h"
16 // Other libraries and framework includes
18 #include "lldb/Core/DataBufferHeap.h"
19 #include "lldb/Core/DataExtractor.h"
20 #include "lldb/Core/Debugger.h"
21 #include "lldb/Core/Module.h"
22 #include "lldb/Core/StreamString.h"
23 #include "lldb/Core/ValueObjectMemory.h"
24 #include "lldb/Interpreter/Args.h"
25 #include "lldb/Interpreter/CommandReturnObject.h"
26 #include "lldb/Interpreter/CommandInterpreter.h"
27 #include "lldb/Interpreter/Options.h"
28 #include "lldb/Interpreter/OptionGroupFormat.h"
29 #include "lldb/Interpreter/OptionGroupOutputFile.h"
30 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
31 #include "lldb/Interpreter/OptionValueString.h"
32 #include "lldb/Symbol/TypeList.h"
33 #include "lldb/Target/Process.h"
34 #include "lldb/Target/StackFrame.h"
37 using namespace lldb_private;
39 static OptionDefinition
42 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
43 { LLDB_OPT_SET_2, false, "binary" ,'b', no_argument , NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
44 { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
47 LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
52 class OptionGroupReadMemory : public OptionGroup
56 OptionGroupReadMemory () :
58 m_output_as_binary (false),
64 ~OptionGroupReadMemory ()
72 return sizeof (g_option_table) / sizeof (OptionDefinition);
75 virtual const OptionDefinition*
78 return g_option_table;
82 SetOptionValue (CommandInterpreter &interpreter,
84 const char *option_arg)
87 const int short_option = g_option_table[option_idx].short_option;
92 error = m_num_per_line.SetValueFromCString (option_arg);
93 if (m_num_per_line.GetCurrentValue() == 0)
94 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
98 m_output_as_binary = true;
102 error = m_view_as_type.SetValueFromCString (option_arg);
110 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
117 OptionParsingStarting (CommandInterpreter &interpreter)
119 m_num_per_line.Clear();
120 m_output_as_binary = false;
121 m_view_as_type.Clear();
126 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
129 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
130 OptionValueUInt64 &count_value = format_options.GetCountValue();
131 const bool byte_size_option_set = byte_size_value.OptionWasSet();
132 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
133 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
135 switch (format_options.GetFormat())
141 if (!byte_size_option_set)
143 if (!num_per_line_option_set)
145 if (!count_option_set)
146 format_options.GetCountValue() = 8;
152 case eFormatInstruction:
153 if (count_option_set)
154 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
158 case eFormatAddressInfo:
159 if (!byte_size_option_set)
160 byte_size_value = target->GetArchitecture().GetAddressByteSize();
162 if (!count_option_set)
163 format_options.GetCountValue() = 8;
167 byte_size_value = target->GetArchitecture().GetAddressByteSize();
168 if (!num_per_line_option_set)
170 if (!count_option_set)
171 format_options.GetCountValue() = 8;
179 case eFormatUnicode16:
180 case eFormatUnicode32:
181 case eFormatUnsigned:
182 case eFormatHexFloat:
183 if (!byte_size_option_set)
185 if (!num_per_line_option_set)
187 if (!count_option_set)
188 format_options.GetCountValue() = 8;
192 case eFormatBytesWithASCII:
193 if (byte_size_option_set)
195 if (byte_size_value > 1)
196 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
197 "\tconsider using a different display format or don't specify the byte size",
198 byte_size_value.GetCurrentValue());
202 if (!num_per_line_option_set)
204 if (!count_option_set)
205 format_options.GetCountValue() = 32;
207 case eFormatCharArray:
209 case eFormatCharPrintable:
210 if (!byte_size_option_set)
212 if (!num_per_line_option_set)
214 if (!count_option_set)
215 format_options.GetCountValue() = 64;
218 if (!byte_size_option_set)
220 if (!num_per_line_option_set)
222 if (!count_option_set)
223 format_options.GetCountValue() = 8;
225 case eFormatComplexInteger:
226 if (!byte_size_option_set)
228 if (!num_per_line_option_set)
230 if (!count_option_set)
231 format_options.GetCountValue() = 8;
234 if (!byte_size_option_set)
236 if (!num_per_line_option_set)
238 switch (byte_size_value)
255 if (!count_option_set)
259 case eFormatVectorOfChar:
260 case eFormatVectorOfSInt8:
261 case eFormatVectorOfUInt8:
262 case eFormatVectorOfSInt16:
263 case eFormatVectorOfUInt16:
264 case eFormatVectorOfSInt32:
265 case eFormatVectorOfUInt32:
266 case eFormatVectorOfSInt64:
267 case eFormatVectorOfUInt64:
268 case eFormatVectorOfFloat32:
269 case eFormatVectorOfFloat64:
270 case eFormatVectorOfUInt128:
271 if (!byte_size_option_set)
272 byte_size_value = 128;
273 if (!num_per_line_option_set)
275 if (!count_option_set)
283 AnyOptionWasSet () const
285 return m_num_per_line.OptionWasSet() ||
286 m_output_as_binary ||
287 m_view_as_type.OptionWasSet();
290 OptionValueUInt64 m_num_per_line;
291 bool m_output_as_binary;
292 OptionValueString m_view_as_type;
298 //----------------------------------------------------------------------
299 // Read memory from the inferior process
300 //----------------------------------------------------------------------
301 class CommandObjectMemoryRead : public CommandObjectParsed
305 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
306 CommandObjectParsed (interpreter,
308 "Read from the memory of the process being debugged.",
310 eFlagRequiresTarget | eFlagProcessMustBePaused),
311 m_option_group (interpreter),
312 m_format_options (eFormatBytesWithASCII, 1, 8),
314 m_outfile_options (),
316 m_next_addr(LLDB_INVALID_ADDRESS),
318 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
319 m_prev_memory_options (),
320 m_prev_outfile_options (),
321 m_prev_varobj_options()
323 CommandArgumentEntry arg1;
324 CommandArgumentEntry arg2;
325 CommandArgumentData start_addr_arg;
326 CommandArgumentData end_addr_arg;
328 // Define the first (and only) variant of this arg.
329 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
330 start_addr_arg.arg_repetition = eArgRepeatPlain;
332 // There is only one variant this argument could be; put it into the argument entry.
333 arg1.push_back (start_addr_arg);
335 // Define the first (and only) variant of this arg.
336 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
337 end_addr_arg.arg_repetition = eArgRepeatOptional;
339 // There is only one variant this argument could be; put it into the argument entry.
340 arg2.push_back (end_addr_arg);
342 // Push the data for the first argument into the m_arguments vector.
343 m_arguments.push_back (arg1);
344 m_arguments.push_back (arg2);
346 // Add the "--format" and "--count" options to group 1 and 3
347 m_option_group.Append (&m_format_options,
348 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
349 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
350 m_option_group.Append (&m_format_options,
351 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
352 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
353 // Add the "--size" option to group 1 and 2
354 m_option_group.Append (&m_format_options,
355 OptionGroupFormat::OPTION_GROUP_SIZE,
356 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
357 m_option_group.Append (&m_memory_options);
358 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
359 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
360 m_option_group.Finalize();
364 ~CommandObjectMemoryRead ()
371 return &m_option_group;
374 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index)
376 return m_cmd_name.c_str();
381 DoExecute (Args& command, CommandReturnObject &result)
383 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
384 Target *target = m_exe_ctx.GetTargetPtr();
386 const size_t argc = command.GetArgumentCount();
388 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
390 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
391 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
392 result.SetStatus(eReturnStatusFailed);
396 ClangASTType clang_ast_type;
399 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
400 if (view_as_type_cstr && view_as_type_cstr[0])
402 // We are viewing memory as a type
405 const bool exact_match = false;
407 uint32_t reference_count = 0;
408 uint32_t pointer_count = 0;
411 #define ALL_KEYWORDS \
413 KEYWORD("volatile") \
414 KEYWORD("restrict") \
419 #define KEYWORD(s) s,
420 static const char *g_keywords[] =
426 #define KEYWORD(s) (sizeof(s) - 1),
427 static const int g_keyword_lengths[] =
435 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
436 std::string type_str(view_as_type_cstr);
438 // Remove all instances of g_keywords that are followed by spaces
439 for (size_t i = 0; i < g_num_keywords; ++i)
441 const char *keyword = g_keywords[i];
442 int keyword_len = g_keyword_lengths[i];
445 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
447 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
449 type_str.erase(idx, keyword_len+1);
458 bool done = type_str.empty();
460 idx = type_str.find_first_not_of (" \t");
461 if (idx > 0 && idx != std::string::npos)
462 type_str.erase (0, idx);
465 // Strip trailing spaces
466 if (type_str.empty())
470 switch (type_str[type_str.size()-1])
477 type_str.erase(type_str.size()-1);
481 if (reference_count == 0)
484 type_str.erase(type_str.size()-1);
488 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
489 result.SetStatus(eReturnStatusFailed);
501 ConstString lookup_type_name(type_str.c_str());
502 StackFrame *frame = m_exe_ctx.GetFramePtr();
505 sc = frame->GetSymbolContext (eSymbolContextModule);
508 sc.module_sp->FindTypes (sc,
515 if (type_list.GetSize() == 0)
517 target->GetImages().FindTypes (sc,
524 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
526 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
529 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
533 if (clang_ast_type.IsValid() == false)
535 if (type_list.GetSize() == 0)
537 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
538 lookup_type_name.GetCString(),
540 result.SetStatus(eReturnStatusFailed);
545 TypeSP type_sp (type_list.GetTypeAtIndex(0));
546 clang_ast_type = type_sp->GetClangFullType();
550 while (pointer_count > 0)
552 ClangASTType pointer_type = clang_ast_type.GetPointerType();
553 if (pointer_type.IsValid())
554 clang_ast_type = pointer_type;
557 result.AppendError ("unable make a pointer type\n");
558 result.SetStatus(eReturnStatusFailed);
564 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize();
566 if (m_format_options.GetByteSizeValue() == 0)
568 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
570 result.SetStatus(eReturnStatusFailed);
574 if (!m_format_options.GetCountValue().OptionWasSet())
575 m_format_options.GetCountValue() = 1;
579 error = m_memory_options.FinalizeSettings (target, m_format_options);
582 // Look for invalid combinations of settings
585 result.AppendError(error.AsCString());
586 result.SetStatus(eReturnStatusFailed);
591 size_t total_byte_size = 0;
594 // Use the last address and byte size and all options as they were
595 // if no options have been set
597 total_byte_size = m_prev_byte_size;
598 clang_ast_type = m_prev_clang_ast_type;
599 if (!m_format_options.AnyOptionWasSet() &&
600 !m_memory_options.AnyOptionWasSet() &&
601 !m_outfile_options.AnyOptionWasSet() &&
602 !m_varobj_options.AnyOptionWasSet())
604 m_format_options = m_prev_format_options;
605 m_memory_options = m_prev_memory_options;
606 m_outfile_options = m_prev_outfile_options;
607 m_varobj_options = m_prev_varobj_options;
611 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
612 size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
613 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
615 if (total_byte_size == 0)
617 total_byte_size = item_count * item_byte_size;
618 if (total_byte_size == 0)
619 total_byte_size = 32;
623 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
625 if (addr == LLDB_INVALID_ADDRESS)
627 result.AppendError("invalid start address expression.");
628 result.AppendError(error.AsCString());
629 result.SetStatus(eReturnStatusFailed);
635 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
636 if (end_addr == LLDB_INVALID_ADDRESS)
638 result.AppendError("invalid end address expression.");
639 result.AppendError(error.AsCString());
640 result.SetStatus(eReturnStatusFailed);
643 else if (end_addr <= addr)
645 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
646 result.SetStatus(eReturnStatusFailed);
649 else if (m_format_options.GetCountValue().OptionWasSet())
651 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count);
652 result.SetStatus(eReturnStatusFailed);
656 total_byte_size = end_addr - addr;
657 item_count = total_byte_size / item_byte_size;
660 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
662 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
664 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
665 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
666 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
670 DataBufferSP data_sp;
671 size_t bytes_read = 0;
672 if (clang_ast_type.GetOpaqueQualType())
674 // Make sure we don't display our type as ASCII bytes like the default memory read
675 if (m_format_options.GetFormatValue().OptionWasSet() == false)
676 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
678 bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue();
680 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
682 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
683 if (data_sp->GetBytes() == NULL)
685 result.AppendErrorWithFormat ("can't allocate 0x%zx bytes for the memory read buffer, specify a smaller size to read", total_byte_size);
686 result.SetStatus(eReturnStatusFailed);
690 Address address(addr, NULL);
691 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
694 const char *error_cstr = error.AsCString();
695 if (error_cstr && error_cstr[0])
697 result.AppendError(error_cstr);
701 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
703 result.SetStatus(eReturnStatusFailed);
707 if (bytes_read < total_byte_size)
708 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
712 // we treat c-strings as a special case because they do not have a fixed size
713 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
714 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
716 item_byte_size = target->GetMaximumSizeOfStringSummary();
717 if (!m_format_options.GetCountValue().OptionWasSet())
719 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
720 if (data_sp->GetBytes() == NULL)
722 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));
723 result.SetStatus(eReturnStatusFailed);
726 uint8_t *data_ptr = data_sp->GetBytes();
727 auto data_addr = addr;
728 auto count = item_count;
730 while (item_count < count)
733 buffer.resize(item_byte_size+1,0);
735 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
738 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
739 result.SetStatus(eReturnStatusFailed);
742 if (item_byte_size == read)
744 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
747 read+=1; // account for final NULL byte
748 memcpy(data_ptr, &buffer[0], read);
752 item_count++; // if we break early we know we only read item_count strings
754 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
757 m_next_addr = addr + bytes_read;
758 m_prev_byte_size = bytes_read;
759 m_prev_format_options = m_format_options;
760 m_prev_memory_options = m_memory_options;
761 m_prev_outfile_options = m_outfile_options;
762 m_prev_varobj_options = m_varobj_options;
763 m_prev_clang_ast_type = clang_ast_type;
765 StreamFile outfile_stream;
766 Stream *output_stream = NULL;
767 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
771 outfile_spec.GetPath (path, sizeof(path));
773 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
774 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
776 open_options |= File::eOpenOptionAppend;
778 if (outfile_stream.GetFile ().Open (path, open_options).Success())
780 if (m_memory_options.m_output_as_binary)
782 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
783 if (bytes_written > 0)
785 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
787 append ? "appended" : "written",
793 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
794 result.SetStatus(eReturnStatusFailed);
800 // We are going to write ASCII to the file just point the
801 // output_stream to our outfile_stream...
802 output_stream = &outfile_stream;
807 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
808 result.SetStatus(eReturnStatusFailed);
814 output_stream = &result.GetOutputStream();
818 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
819 if (clang_ast_type.GetOpaqueQualType())
821 for (uint32_t i = 0; i<item_count; ++i)
823 addr_t item_addr = addr + (i * item_byte_size);
824 Address address (item_addr);
825 StreamString name_strm;
826 name_strm.Printf ("0x%" PRIx64, item_addr);
827 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
828 name_strm.GetString().c_str(),
833 Format format = m_format_options.GetFormat();
834 if (format != eFormatDefault)
835 valobj_sp->SetFormat (format);
837 ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format));
839 ValueObject::DumpValueObject (*output_stream,
845 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
847 name_strm.GetString().c_str());
848 result.SetStatus(eReturnStatusFailed);
855 result.SetStatus(eReturnStatusSuccessFinishResult);
856 DataExtractor data (data_sp,
857 target->GetArchitecture().GetByteOrder(),
858 target->GetArchitecture().GetAddressByteSize());
860 Format format = m_format_options.GetFormat();
861 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
862 && (item_byte_size != 1)
863 && (item_count == 1))
865 // this turns requests such as
866 // memory read -fc -s10 -c1 *charPtrPtr
867 // which make no sense (what is a char of size 10?)
868 // into a request for fetching 10 chars of size 1 from the same memory location
869 format = eFormatCharArray;
870 item_count = item_byte_size;
874 assert (output_stream);
875 size_t bytes_dumped = data.Dump (output_stream,
885 m_next_addr = addr + bytes_dumped;
886 output_stream->EOL();
890 OptionGroupOptions m_option_group;
891 OptionGroupFormat m_format_options;
892 OptionGroupReadMemory m_memory_options;
893 OptionGroupOutputFile m_outfile_options;
894 OptionGroupValueObjectDisplay m_varobj_options;
895 lldb::addr_t m_next_addr;
896 lldb::addr_t m_prev_byte_size;
897 OptionGroupFormat m_prev_format_options;
898 OptionGroupReadMemory m_prev_memory_options;
899 OptionGroupOutputFile m_prev_outfile_options;
900 OptionGroupValueObjectDisplay m_prev_varobj_options;
901 ClangASTType m_prev_clang_ast_type;
906 g_memory_write_option_table[] =
908 { LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
909 { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
913 //----------------------------------------------------------------------
914 // Write memory to the inferior process
915 //----------------------------------------------------------------------
916 class CommandObjectMemoryWrite : public CommandObjectParsed
920 class OptionGroupWriteMemory : public OptionGroup
923 OptionGroupWriteMemory () :
929 ~OptionGroupWriteMemory ()
936 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
939 virtual const OptionDefinition*
942 return g_memory_write_option_table;
946 SetOptionValue (CommandInterpreter &interpreter,
948 const char *option_arg)
951 const int short_option = g_memory_write_option_table[option_idx].short_option;
953 switch (short_option)
956 m_infile.SetFile (option_arg, true);
957 if (!m_infile.Exists())
960 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
967 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
970 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
976 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
983 OptionParsingStarting (CommandInterpreter &interpreter)
990 off_t m_infile_offset;
993 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
994 CommandObjectParsed (interpreter,
996 "Write to the memory of the process being debugged.",
998 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
999 m_option_group (interpreter),
1000 m_format_options (eFormatBytes, 1, UINT64_MAX),
1003 CommandArgumentEntry arg1;
1004 CommandArgumentEntry arg2;
1005 CommandArgumentData addr_arg;
1006 CommandArgumentData value_arg;
1008 // Define the first (and only) variant of this arg.
1009 addr_arg.arg_type = eArgTypeAddress;
1010 addr_arg.arg_repetition = eArgRepeatPlain;
1012 // There is only one variant this argument could be; put it into the argument entry.
1013 arg1.push_back (addr_arg);
1015 // Define the first (and only) variant of this arg.
1016 value_arg.arg_type = eArgTypeValue;
1017 value_arg.arg_repetition = eArgRepeatPlus;
1019 // There is only one variant this argument could be; put it into the argument entry.
1020 arg2.push_back (value_arg);
1022 // Push the data for the first argument into the m_arguments vector.
1023 m_arguments.push_back (arg1);
1024 m_arguments.push_back (arg2);
1026 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1027 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1028 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1029 m_option_group.Finalize();
1034 ~CommandObjectMemoryWrite ()
1041 return &m_option_group;
1045 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1047 if (total_byte_size > 8)
1050 if (total_byte_size == 8)
1053 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1054 return uval64 <= max;
1058 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1060 if (total_byte_size > 8)
1063 if (total_byte_size == 8)
1066 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1067 const int64_t min = ~(max);
1068 return min <= sval64 && sval64 <= max;
1073 DoExecute (Args& command, CommandReturnObject &result)
1075 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1076 Process *process = m_exe_ctx.GetProcessPtr();
1078 const size_t argc = command.GetArgumentCount();
1080 if (m_memory_options.m_infile)
1084 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1085 result.SetStatus(eReturnStatusFailed);
1091 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
1092 result.SetStatus(eReturnStatusFailed);
1096 StreamString buffer (Stream::eBinary,
1097 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1098 process->GetTarget().GetArchitecture().GetByteOrder());
1100 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1101 size_t item_byte_size = byte_size_value.GetCurrentValue();
1104 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1105 command.GetArgumentAtIndex(0),
1106 LLDB_INVALID_ADDRESS,
1109 if (addr == LLDB_INVALID_ADDRESS)
1111 result.AppendError("invalid address expression\n");
1112 result.AppendError(error.AsCString());
1113 result.SetStatus(eReturnStatusFailed);
1117 if (m_memory_options.m_infile)
1119 size_t length = SIZE_MAX;
1120 if (item_byte_size > 0)
1121 length = item_byte_size;
1122 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
1125 length = data_sp->GetByteSize();
1129 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1131 if (bytes_written == length)
1133 // All bytes written
1134 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
1135 result.SetStatus(eReturnStatusSuccessFinishResult);
1137 else if (bytes_written > 0)
1139 // Some byte written
1140 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
1141 result.SetStatus(eReturnStatusSuccessFinishResult);
1145 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1146 result.SetStatus(eReturnStatusFailed);
1152 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1153 result.SetStatus(eReturnStatusFailed);
1155 return result.Succeeded();
1157 else if (item_byte_size == 0)
1159 if (m_format_options.GetFormat() == eFormatPointer)
1160 item_byte_size = buffer.GetAddressByteSize();
1165 command.Shift(); // shift off the address argument
1168 bool success = false;
1169 const size_t num_value_args = command.GetArgumentCount();
1170 for (size_t i=0; i<num_value_args; ++i)
1172 const char *value_str = command.GetArgumentAtIndex(i);
1174 switch (m_format_options.GetFormat())
1177 case eFormatFloat: // TODO: add support for floats soon
1178 case eFormatCharPrintable:
1179 case eFormatBytesWithASCII:
1180 case eFormatComplex:
1182 case eFormatUnicode16:
1183 case eFormatUnicode32:
1184 case eFormatVectorOfChar:
1185 case eFormatVectorOfSInt8:
1186 case eFormatVectorOfUInt8:
1187 case eFormatVectorOfSInt16:
1188 case eFormatVectorOfUInt16:
1189 case eFormatVectorOfSInt32:
1190 case eFormatVectorOfUInt32:
1191 case eFormatVectorOfSInt64:
1192 case eFormatVectorOfUInt64:
1193 case eFormatVectorOfFloat32:
1194 case eFormatVectorOfFloat64:
1195 case eFormatVectorOfUInt128:
1197 case eFormatComplexInteger:
1198 case eFormatAddressInfo:
1199 case eFormatHexFloat:
1200 case eFormatInstruction:
1202 result.AppendError("unsupported format for writing memory");
1203 result.SetStatus(eReturnStatusFailed);
1206 case eFormatDefault:
1209 case eFormatHexUppercase:
1210 case eFormatPointer:
1213 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1216 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1217 result.SetStatus(eReturnStatusFailed);
1220 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1222 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1223 result.SetStatus(eReturnStatusFailed);
1226 buffer.PutMaxHex64 (uval64, item_byte_size);
1229 case eFormatBoolean:
1230 uval64 = Args::StringToBoolean(value_str, false, &success);
1233 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1234 result.SetStatus(eReturnStatusFailed);
1237 buffer.PutMaxHex64 (uval64, item_byte_size);
1241 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1244 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1245 result.SetStatus(eReturnStatusFailed);
1248 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1250 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1251 result.SetStatus(eReturnStatusFailed);
1254 buffer.PutMaxHex64 (uval64, item_byte_size);
1257 case eFormatCharArray:
1259 case eFormatCString:
1262 size_t len = strlen (value_str);
1263 // Include the NULL for C strings...
1264 if (m_format_options.GetFormat() == eFormatCString)
1267 if (process->WriteMemory (addr, value_str, len, error) == len)
1273 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1274 result.SetStatus(eReturnStatusFailed);
1280 case eFormatDecimal:
1281 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1284 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1285 result.SetStatus(eReturnStatusFailed);
1288 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1290 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
1291 result.SetStatus(eReturnStatusFailed);
1294 buffer.PutMaxHex64 (sval64, item_byte_size);
1297 case eFormatUnsigned:
1298 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1301 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1302 result.SetStatus(eReturnStatusFailed);
1305 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1307 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1308 result.SetStatus(eReturnStatusFailed);
1311 buffer.PutMaxHex64 (uval64, item_byte_size);
1315 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1318 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1319 result.SetStatus(eReturnStatusFailed);
1322 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1324 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
1325 result.SetStatus(eReturnStatusFailed);
1328 buffer.PutMaxHex64 (uval64, item_byte_size);
1333 if (!buffer.GetString().empty())
1336 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
1340 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1341 result.SetStatus(eReturnStatusFailed);
1348 OptionGroupOptions m_option_group;
1349 OptionGroupFormat m_format_options;
1350 OptionGroupWriteMemory m_memory_options;
1354 //-------------------------------------------------------------------------
1355 // CommandObjectMemory
1356 //-------------------------------------------------------------------------
1358 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
1359 CommandObjectMultiword (interpreter,
1361 "A set of commands for operating on memory.",
1362 "memory <subcommand> [<subcommand-options>]")
1364 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1365 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
1368 CommandObjectMemory::~CommandObjectMemory ()