Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1 | //===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #include "CommandObjectMemory.h" |
| 11 | |
| 12 | // C Includes |
| 13 | // C++ Includes |
| 14 | // Other libraries and framework includes |
| 15 | // Project includes |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 16 | #include "lldb/Core/DataBufferHeap.h" |
| 17 | #include "lldb/Core/DataExtractor.h" |
Greg Clayton | 63094e0 | 2010-06-23 01:19:29 +0000 | [diff] [blame] | 18 | #include "lldb/Core/Debugger.h" |
Greg Clayton | 49ce896 | 2012-08-29 21:13:06 +0000 | [diff] [blame] | 19 | #include "lldb/Core/Module.h" |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 20 | #include "lldb/Core/StreamString.h" |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 21 | #include "lldb/Core/ValueObjectMemory.h" |
Greg Clayton | 63094e0 | 2010-06-23 01:19:29 +0000 | [diff] [blame] | 22 | #include "lldb/Interpreter/Args.h" |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 23 | #include "lldb/Interpreter/CommandReturnObject.h" |
Greg Clayton | 63094e0 | 2010-06-23 01:19:29 +0000 | [diff] [blame] | 24 | #include "lldb/Interpreter/CommandInterpreter.h" |
| 25 | #include "lldb/Interpreter/Options.h" |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 26 | #include "lldb/Interpreter/OptionGroupFormat.h" |
| 27 | #include "lldb/Interpreter/OptionGroupOutputFile.h" |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 28 | #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" |
Greg Clayton | 73844aa | 2012-08-22 17:17:09 +0000 | [diff] [blame] | 29 | #include "lldb/Interpreter/OptionValueString.h" |
Greg Clayton | 49ce896 | 2012-08-29 21:13:06 +0000 | [diff] [blame] | 30 | #include "lldb/Symbol/TypeList.h" |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 31 | #include "lldb/Target/Process.h" |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 32 | #include "lldb/Target/StackFrame.h" |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 33 | |
| 34 | using namespace lldb; |
| 35 | using namespace lldb_private; |
| 36 | |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 37 | static OptionDefinition |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 38 | g_option_table[] = |
| 39 | { |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 40 | { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, |
| 41 | { 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."}, |
Sean Callanan | 06dc17f | 2012-09-24 22:25:51 +0000 | [diff] [blame] | 42 | { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, |
Sean Callanan | 8a6f3e9 | 2012-04-28 01:27:38 +0000 | [diff] [blame] | 43 | { LLDB_OPT_SET_4, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over 1024 bytes of memory."}, |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 44 | }; |
| 45 | |
| 46 | |
| 47 | |
| 48 | class OptionGroupReadMemory : public OptionGroup |
| 49 | { |
| 50 | public: |
| 51 | |
| 52 | OptionGroupReadMemory () : |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 53 | m_num_per_line (1,1), |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 54 | m_output_as_binary (false), |
| 55 | m_view_as_type() |
| 56 | { |
| 57 | } |
| 58 | |
| 59 | virtual |
| 60 | ~OptionGroupReadMemory () |
| 61 | { |
| 62 | } |
| 63 | |
| 64 | |
| 65 | virtual uint32_t |
| 66 | GetNumDefinitions () |
| 67 | { |
| 68 | return sizeof (g_option_table) / sizeof (OptionDefinition); |
| 69 | } |
| 70 | |
| 71 | virtual const OptionDefinition* |
| 72 | GetDefinitions () |
| 73 | { |
| 74 | return g_option_table; |
| 75 | } |
| 76 | |
| 77 | virtual Error |
| 78 | SetOptionValue (CommandInterpreter &interpreter, |
| 79 | uint32_t option_idx, |
| 80 | const char *option_arg) |
| 81 | { |
| 82 | Error error; |
| 83 | char short_option = (char) g_option_table[option_idx].short_option; |
| 84 | |
| 85 | switch (short_option) |
| 86 | { |
| 87 | case 'l': |
| 88 | error = m_num_per_line.SetValueFromCString (option_arg); |
| 89 | if (m_num_per_line.GetCurrentValue() == 0) |
Greg Clayton | 9c23673 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 90 | error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 91 | break; |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 92 | |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 93 | case 'b': |
| 94 | m_output_as_binary = true; |
| 95 | break; |
| 96 | |
| 97 | case 't': |
| 98 | error = m_view_as_type.SetValueFromCString (option_arg); |
| 99 | break; |
Sean Callanan | 8a6f3e9 | 2012-04-28 01:27:38 +0000 | [diff] [blame] | 100 | |
| 101 | case 'r': |
| 102 | m_force = true; |
| 103 | break; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 104 | |
| 105 | default: |
Greg Clayton | 9c23673 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 106 | error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 107 | break; |
| 108 | } |
| 109 | return error; |
| 110 | } |
| 111 | |
| 112 | virtual void |
| 113 | OptionParsingStarting (CommandInterpreter &interpreter) |
| 114 | { |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 115 | m_num_per_line.Clear(); |
| 116 | m_output_as_binary = false; |
| 117 | m_view_as_type.Clear(); |
| 118 | } |
| 119 | |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 120 | Error |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 121 | FinalizeSettings (Target *target, OptionGroupFormat& format_options) |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 122 | { |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 123 | Error error; |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 124 | OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue(); |
| 125 | OptionValueUInt64 &count_value = format_options.GetCountValue(); |
Greg Clayton | 9c23673 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 126 | const bool byte_size_option_set = byte_size_value.OptionWasSet(); |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 127 | const bool num_per_line_option_set = m_num_per_line.OptionWasSet(); |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 128 | const bool count_option_set = format_options.GetCountValue().OptionWasSet(); |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 129 | |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 130 | switch (format_options.GetFormat()) |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 131 | { |
| 132 | default: |
| 133 | break; |
| 134 | |
| 135 | case eFormatBoolean: |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 136 | if (!byte_size_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 137 | byte_size_value = 1; |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 138 | if (!num_per_line_option_set) |
| 139 | m_num_per_line = 1; |
| 140 | if (!count_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 141 | format_options.GetCountValue() = 8; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 142 | break; |
| 143 | |
| 144 | case eFormatCString: |
| 145 | break; |
Greg Clayton | 24a6bd9 | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 146 | |
| 147 | case eFormatInstruction: |
| 148 | if (count_option_set) |
| 149 | byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue(); |
| 150 | m_num_per_line = 1; |
| 151 | break; |
| 152 | |
| 153 | case eFormatAddressInfo: |
| 154 | if (!byte_size_option_set) |
| 155 | byte_size_value = target->GetArchitecture().GetAddressByteSize(); |
| 156 | m_num_per_line = 1; |
| 157 | if (!count_option_set) |
| 158 | format_options.GetCountValue() = 8; |
| 159 | break; |
| 160 | |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 161 | case eFormatPointer: |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 162 | byte_size_value = target->GetArchitecture().GetAddressByteSize(); |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 163 | if (!num_per_line_option_set) |
| 164 | m_num_per_line = 4; |
| 165 | if (!count_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 166 | format_options.GetCountValue() = 8; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 167 | break; |
| 168 | |
| 169 | case eFormatBinary: |
| 170 | case eFormatFloat: |
| 171 | case eFormatOctal: |
| 172 | case eFormatDecimal: |
| 173 | case eFormatEnum: |
| 174 | case eFormatUnicode16: |
| 175 | case eFormatUnicode32: |
| 176 | case eFormatUnsigned: |
Greg Clayton | 24a6bd9 | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 177 | case eFormatHexFloat: |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 178 | if (!byte_size_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 179 | byte_size_value = 4; |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 180 | if (!num_per_line_option_set) |
| 181 | m_num_per_line = 1; |
| 182 | if (!count_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 183 | format_options.GetCountValue() = 8; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 184 | break; |
Greg Clayton | 24a6bd9 | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 185 | |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 186 | case eFormatBytes: |
| 187 | case eFormatBytesWithASCII: |
Greg Clayton | 9c23673 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 188 | if (byte_size_option_set) |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 189 | { |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 190 | if (byte_size_value > 1) |
Johnny Chen | bf9ba59 | 2012-03-06 01:17:59 +0000 | [diff] [blame] | 191 | error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n" |
| 192 | "\tconsider using a different display format or don't specify the byte size", |
| 193 | byte_size_value.GetCurrentValue()); |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 194 | } |
| 195 | else |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 196 | byte_size_value = 1; |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 197 | if (!num_per_line_option_set) |
| 198 | m_num_per_line = 16; |
| 199 | if (!count_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 200 | format_options.GetCountValue() = 32; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 201 | break; |
Greg Clayton | 307fa07 | 2011-06-17 23:50:44 +0000 | [diff] [blame] | 202 | case eFormatCharArray: |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 203 | case eFormatChar: |
| 204 | case eFormatCharPrintable: |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 205 | if (!byte_size_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 206 | byte_size_value = 1; |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 207 | if (!num_per_line_option_set) |
| 208 | m_num_per_line = 32; |
| 209 | if (!count_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 210 | format_options.GetCountValue() = 64; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 211 | break; |
| 212 | case eFormatComplex: |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 213 | if (!byte_size_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 214 | byte_size_value = 8; |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 215 | if (!num_per_line_option_set) |
| 216 | m_num_per_line = 1; |
| 217 | if (!count_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 218 | format_options.GetCountValue() = 8; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 219 | break; |
| 220 | case eFormatHex: |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 221 | if (!byte_size_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 222 | byte_size_value = 4; |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 223 | if (!num_per_line_option_set) |
| 224 | { |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 225 | switch (byte_size_value) |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 226 | { |
| 227 | case 1: |
| 228 | case 2: |
| 229 | m_num_per_line = 8; |
| 230 | break; |
| 231 | case 4: |
| 232 | m_num_per_line = 4; |
| 233 | break; |
| 234 | case 8: |
| 235 | m_num_per_line = 2; |
| 236 | break; |
| 237 | default: |
| 238 | m_num_per_line = 1; |
| 239 | break; |
| 240 | } |
| 241 | } |
| 242 | if (!count_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 243 | count_value = 8; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 244 | break; |
| 245 | |
| 246 | case eFormatVectorOfChar: |
| 247 | case eFormatVectorOfSInt8: |
| 248 | case eFormatVectorOfUInt8: |
| 249 | case eFormatVectorOfSInt16: |
| 250 | case eFormatVectorOfUInt16: |
| 251 | case eFormatVectorOfSInt32: |
| 252 | case eFormatVectorOfUInt32: |
| 253 | case eFormatVectorOfSInt64: |
| 254 | case eFormatVectorOfUInt64: |
| 255 | case eFormatVectorOfFloat32: |
| 256 | case eFormatVectorOfFloat64: |
| 257 | case eFormatVectorOfUInt128: |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 258 | if (!byte_size_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 259 | byte_size_value = 128; |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 260 | if (!num_per_line_option_set) |
| 261 | m_num_per_line = 1; |
| 262 | if (!count_option_set) |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 263 | count_value = 4; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 264 | break; |
| 265 | } |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 266 | return error; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 267 | } |
| 268 | |
Greg Clayton | 902b5be | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 269 | bool |
| 270 | AnyOptionWasSet () const |
| 271 | { |
| 272 | return m_num_per_line.OptionWasSet() || |
| 273 | m_output_as_binary || |
| 274 | m_view_as_type.OptionWasSet(); |
| 275 | } |
| 276 | |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 277 | OptionValueUInt64 m_num_per_line; |
| 278 | bool m_output_as_binary; |
| 279 | OptionValueString m_view_as_type; |
Sean Callanan | 8a6f3e9 | 2012-04-28 01:27:38 +0000 | [diff] [blame] | 280 | bool m_force; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 281 | }; |
| 282 | |
| 283 | |
| 284 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 285 | //---------------------------------------------------------------------- |
| 286 | // Read memory from the inferior process |
| 287 | //---------------------------------------------------------------------- |
Jim Ingham | da26bd2 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 288 | class CommandObjectMemoryRead : public CommandObjectParsed |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 289 | { |
| 290 | public: |
| 291 | |
Greg Clayton | 238c0a1 | 2010-09-18 01:14:36 +0000 | [diff] [blame] | 292 | CommandObjectMemoryRead (CommandInterpreter &interpreter) : |
Jim Ingham | da26bd2 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 293 | CommandObjectParsed (interpreter, |
| 294 | "memory read", |
| 295 | "Read from the memory of the process being debugged.", |
| 296 | NULL, |
| 297 | eFlagProcessMustBePaused), |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 298 | m_option_group (interpreter), |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 299 | m_format_options (eFormatBytesWithASCII, 1, 8), |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 300 | m_memory_options (), |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 301 | m_outfile_options (), |
Greg Clayton | 902b5be | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 302 | m_varobj_options(), |
| 303 | m_next_addr(LLDB_INVALID_ADDRESS), |
| 304 | m_prev_byte_size(0), |
| 305 | m_prev_format_options (eFormatBytesWithASCII, 1, 8), |
| 306 | m_prev_memory_options (), |
| 307 | m_prev_outfile_options (), |
| 308 | m_prev_varobj_options() |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 309 | { |
Caroline Tice | 43b014a | 2010-10-04 22:28:36 +0000 | [diff] [blame] | 310 | CommandArgumentEntry arg1; |
| 311 | CommandArgumentEntry arg2; |
| 312 | CommandArgumentData start_addr_arg; |
| 313 | CommandArgumentData end_addr_arg; |
| 314 | |
| 315 | // Define the first (and only) variant of this arg. |
| 316 | start_addr_arg.arg_type = eArgTypeStartAddress; |
| 317 | start_addr_arg.arg_repetition = eArgRepeatPlain; |
| 318 | |
| 319 | // There is only one variant this argument could be; put it into the argument entry. |
| 320 | arg1.push_back (start_addr_arg); |
| 321 | |
| 322 | // Define the first (and only) variant of this arg. |
| 323 | end_addr_arg.arg_type = eArgTypeEndAddress; |
| 324 | end_addr_arg.arg_repetition = eArgRepeatOptional; |
| 325 | |
| 326 | // There is only one variant this argument could be; put it into the argument entry. |
| 327 | arg2.push_back (end_addr_arg); |
| 328 | |
| 329 | // Push the data for the first argument into the m_arguments vector. |
| 330 | m_arguments.push_back (arg1); |
| 331 | m_arguments.push_back (arg2); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 332 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 333 | // Add the "--format" and "--count" options to group 1 and 3 |
| 334 | m_option_group.Append (&m_format_options, |
| 335 | OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT, |
Greg Clayton | 31feaa8 | 2011-11-22 18:07:35 +0000 | [diff] [blame] | 336 | LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); |
Greg Clayton | 24a6bd9 | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 337 | m_option_group.Append (&m_format_options, |
| 338 | OptionGroupFormat::OPTION_GROUP_GDB_FMT, |
Greg Clayton | 31feaa8 | 2011-11-22 18:07:35 +0000 | [diff] [blame] | 339 | LLDB_OPT_SET_1 | LLDB_OPT_SET_3); |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 340 | // Add the "--size" option to group 1 and 2 |
| 341 | m_option_group.Append (&m_format_options, |
| 342 | OptionGroupFormat::OPTION_GROUP_SIZE, |
| 343 | LLDB_OPT_SET_1 | LLDB_OPT_SET_2); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 344 | m_option_group.Append (&m_memory_options); |
| 345 | m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 346 | m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 347 | m_option_group.Finalize(); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 348 | } |
| 349 | |
| 350 | virtual |
| 351 | ~CommandObjectMemoryRead () |
| 352 | { |
| 353 | } |
| 354 | |
| 355 | Options * |
| 356 | GetOptions () |
| 357 | { |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 358 | return &m_option_group; |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 359 | } |
| 360 | |
Greg Clayton | 902b5be | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 361 | virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) |
| 362 | { |
| 363 | return m_cmd_name.c_str(); |
| 364 | } |
| 365 | |
Jim Ingham | da26bd2 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 366 | protected: |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 367 | virtual bool |
Jim Ingham | da26bd2 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 368 | DoExecute (Args& command, |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 369 | CommandReturnObject &result) |
| 370 | { |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 371 | ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); |
Greg Clayton | 567e7f3 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 372 | Target *target = exe_ctx.GetTargetPtr(); |
| 373 | if (target == NULL) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 374 | { |
Jim Ingham | 8cc3f69 | 2011-07-09 00:55:34 +0000 | [diff] [blame] | 375 | result.AppendError("need at least a target to read memory"); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 376 | result.SetStatus(eReturnStatusFailed); |
| 377 | return false; |
| 378 | } |
| 379 | const size_t argc = command.GetArgumentCount(); |
| 380 | |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 381 | |
Greg Clayton | 902b5be | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 382 | if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 383 | { |
| 384 | result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str()); |
| 385 | result.SetStatus(eReturnStatusFailed); |
| 386 | return false; |
| 387 | } |
| 388 | |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 389 | ClangASTType clang_ast_type; |
| 390 | Error error; |
| 391 | |
| 392 | Format format = m_format_options.GetFormat(); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 393 | const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); |
| 394 | if (view_as_type_cstr && view_as_type_cstr[0]) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 395 | { |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 396 | // We are viewing memory as a type |
| 397 | SymbolContext sc; |
Greg Clayton | dc0a38c | 2012-03-26 23:03:23 +0000 | [diff] [blame] | 398 | const bool exact_match = false; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 399 | TypeList type_list; |
| 400 | uint32_t reference_count = 0; |
| 401 | uint32_t pointer_count = 0; |
| 402 | size_t idx; |
Sean Callanan | ddb2ece | 2012-07-10 21:24:26 +0000 | [diff] [blame] | 403 | |
| 404 | #define ALL_KEYWORDS \ |
| 405 | KEYWORD("const") \ |
| 406 | KEYWORD("volatile") \ |
| 407 | KEYWORD("restrict") \ |
| 408 | KEYWORD("struct") \ |
| 409 | KEYWORD("class") \ |
| 410 | KEYWORD("union") |
| 411 | |
| 412 | #define KEYWORD(s) s, |
| 413 | static const char *g_keywords[] = |
| 414 | { |
| 415 | ALL_KEYWORDS |
| 416 | }; |
| 417 | #undef KEYWORD |
| 418 | |
| 419 | #define KEYWORD(s) (sizeof(s) - 1), |
| 420 | static const int g_keyword_lengths[] = |
| 421 | { |
| 422 | ALL_KEYWORDS |
| 423 | }; |
| 424 | #undef KEYWORD |
| 425 | |
| 426 | #undef ALL_KEYWORDS |
| 427 | |
| 428 | static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 429 | std::string type_str(view_as_type_cstr); |
| 430 | |
| 431 | // Remove all instances of g_keywords that are followed by spaces |
| 432 | for (size_t i = 0; i < g_num_keywords; ++i) |
| 433 | { |
| 434 | const char *keyword = g_keywords[i]; |
Sean Callanan | ddb2ece | 2012-07-10 21:24:26 +0000 | [diff] [blame] | 435 | int keyword_len = g_keyword_lengths[i]; |
| 436 | |
| 437 | idx = 0; |
| 438 | while ((idx = type_str.find (keyword, idx)) != std::string::npos) |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 439 | { |
| 440 | if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t') |
Sean Callanan | ddb2ece | 2012-07-10 21:24:26 +0000 | [diff] [blame] | 441 | { |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 442 | type_str.erase(idx, keyword_len+1); |
Sean Callanan | ddb2ece | 2012-07-10 21:24:26 +0000 | [diff] [blame] | 443 | idx = 0; |
| 444 | } |
| 445 | else |
| 446 | { |
| 447 | idx += keyword_len; |
| 448 | } |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 449 | } |
| 450 | } |
| 451 | bool done = type_str.empty(); |
| 452 | // |
| 453 | idx = type_str.find_first_not_of (" \t"); |
| 454 | if (idx > 0 && idx != std::string::npos) |
| 455 | type_str.erase (0, idx); |
| 456 | while (!done) |
| 457 | { |
| 458 | // Strip trailing spaces |
| 459 | if (type_str.empty()) |
| 460 | done = true; |
| 461 | else |
| 462 | { |
| 463 | switch (type_str[type_str.size()-1]) |
| 464 | { |
| 465 | case '*': |
| 466 | ++pointer_count; |
| 467 | // fall through... |
| 468 | case ' ': |
| 469 | case '\t': |
| 470 | type_str.erase(type_str.size()-1); |
| 471 | break; |
| 472 | |
| 473 | case '&': |
| 474 | if (reference_count == 0) |
| 475 | { |
| 476 | reference_count = 1; |
| 477 | type_str.erase(type_str.size()-1); |
| 478 | } |
| 479 | else |
| 480 | { |
| 481 | result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr); |
| 482 | result.SetStatus(eReturnStatusFailed); |
| 483 | return false; |
| 484 | } |
| 485 | break; |
| 486 | |
| 487 | default: |
| 488 | done = true; |
| 489 | break; |
| 490 | } |
| 491 | } |
| 492 | } |
| 493 | |
| 494 | ConstString lookup_type_name(type_str.c_str()); |
Greg Clayton | 567e7f3 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 495 | StackFrame *frame = exe_ctx.GetFramePtr(); |
| 496 | if (frame) |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 497 | { |
Greg Clayton | 567e7f3 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 498 | sc = frame->GetSymbolContext (eSymbolContextModule); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 499 | if (sc.module_sp) |
| 500 | { |
Sean Callanan | 3e80cd9 | 2011-10-12 02:08:07 +0000 | [diff] [blame] | 501 | sc.module_sp->FindTypes (sc, |
| 502 | lookup_type_name, |
Greg Clayton | dc0a38c | 2012-03-26 23:03:23 +0000 | [diff] [blame] | 503 | exact_match, |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 504 | 1, |
| 505 | type_list); |
| 506 | } |
| 507 | } |
| 508 | if (type_list.GetSize() == 0) |
| 509 | { |
Greg Clayton | 9f95fb6 | 2012-04-06 17:41:13 +0000 | [diff] [blame] | 510 | target->GetImages().FindTypes (sc, |
Greg Clayton | 567e7f3 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 511 | lookup_type_name, |
Greg Clayton | dc0a38c | 2012-03-26 23:03:23 +0000 | [diff] [blame] | 512 | exact_match, |
Greg Clayton | 567e7f3 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 513 | 1, |
| 514 | type_list); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 515 | } |
| 516 | |
| 517 | if (type_list.GetSize() == 0) |
| 518 | { |
| 519 | result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n", |
| 520 | lookup_type_name.GetCString(), |
| 521 | view_as_type_cstr); |
| 522 | result.SetStatus(eReturnStatusFailed); |
| 523 | return false; |
| 524 | } |
| 525 | |
| 526 | TypeSP type_sp (type_list.GetTypeAtIndex(0)); |
| 527 | clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType()); |
| 528 | |
| 529 | while (pointer_count > 0) |
| 530 | { |
| 531 | clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType()); |
| 532 | if (pointer_type) |
| 533 | clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type); |
| 534 | else |
| 535 | { |
| 536 | result.AppendError ("unable make a pointer type\n"); |
| 537 | result.SetStatus(eReturnStatusFailed); |
| 538 | return false; |
| 539 | } |
| 540 | --pointer_count; |
| 541 | } |
| 542 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 543 | m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 544 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 545 | if (m_format_options.GetByteSizeValue() == 0) |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 546 | { |
| 547 | result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n", |
| 548 | view_as_type_cstr); |
| 549 | result.SetStatus(eReturnStatusFailed); |
| 550 | return false; |
| 551 | } |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 552 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 553 | if (!m_format_options.GetCountValue().OptionWasSet()) |
| 554 | m_format_options.GetCountValue() = 1; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 555 | } |
| 556 | else |
| 557 | { |
Greg Clayton | 567e7f3 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 558 | error = m_memory_options.FinalizeSettings (target, m_format_options); |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 559 | } |
| 560 | |
| 561 | // Look for invalid combinations of settings |
| 562 | if (error.Fail()) |
| 563 | { |
| 564 | result.AppendErrorWithFormat("%s", error.AsCString()); |
| 565 | result.SetStatus(eReturnStatusFailed); |
| 566 | return false; |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 567 | } |
| 568 | |
Greg Clayton | 902b5be | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 569 | lldb::addr_t addr; |
| 570 | size_t total_byte_size = 0; |
| 571 | if (argc == 0) |
| 572 | { |
| 573 | // Use the last address and byte size and all options as they were |
| 574 | // if no options have been set |
| 575 | addr = m_next_addr; |
| 576 | total_byte_size = m_prev_byte_size; |
| 577 | if (!m_format_options.AnyOptionWasSet() && |
| 578 | !m_memory_options.AnyOptionWasSet() && |
| 579 | !m_outfile_options.AnyOptionWasSet() && |
| 580 | !m_varobj_options.AnyOptionWasSet()) |
| 581 | { |
| 582 | m_format_options = m_prev_format_options; |
| 583 | m_memory_options = m_prev_memory_options; |
| 584 | m_outfile_options = m_prev_outfile_options; |
| 585 | m_varobj_options = m_prev_varobj_options; |
| 586 | } |
| 587 | } |
| 588 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 589 | size_t item_count = m_format_options.GetCountValue().GetCurrentValue(); |
| 590 | const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue(); |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 591 | const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue(); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 592 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 593 | if (total_byte_size == 0) |
Greg Clayton | 902b5be | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 594 | { |
| 595 | total_byte_size = item_count * item_byte_size; |
| 596 | if (total_byte_size == 0) |
| 597 | total_byte_size = 32; |
| 598 | } |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 599 | |
Greg Clayton | 902b5be | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 600 | if (argc > 0) |
| 601 | addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 602 | |
| 603 | if (addr == LLDB_INVALID_ADDRESS) |
| 604 | { |
| 605 | result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0)); |
| 606 | result.SetStatus(eReturnStatusFailed); |
| 607 | return false; |
| 608 | } |
| 609 | |
| 610 | if (argc == 2) |
| 611 | { |
| 612 | lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0); |
| 613 | if (end_addr == LLDB_INVALID_ADDRESS) |
| 614 | { |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 615 | result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1)); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 616 | result.SetStatus(eReturnStatusFailed); |
| 617 | return false; |
| 618 | } |
| 619 | else if (end_addr <= addr) |
| 620 | { |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 621 | result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 622 | result.SetStatus(eReturnStatusFailed); |
| 623 | return false; |
| 624 | } |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 625 | else if (m_format_options.GetCountValue().OptionWasSet()) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 626 | { |
Jason Molenda | 7e5fa7f | 2011-09-20 21:44:10 +0000 | [diff] [blame] | 627 | result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 628 | result.SetStatus(eReturnStatusFailed); |
| 629 | return false; |
| 630 | } |
| 631 | |
| 632 | total_byte_size = end_addr - addr; |
| 633 | item_count = total_byte_size / item_byte_size; |
| 634 | } |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 635 | |
Sean Callanan | 8a6f3e9 | 2012-04-28 01:27:38 +0000 | [diff] [blame] | 636 | if (total_byte_size > 1024 && !m_memory_options.m_force) |
| 637 | { |
| 638 | result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n"); |
| 639 | result.AppendErrorWithFormat("Please use --force to override this restriction.\n"); |
| 640 | return false; |
| 641 | } |
| 642 | |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 643 | DataBufferSP data_sp; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 644 | size_t bytes_read = 0; |
| 645 | if (!clang_ast_type.GetOpaqueQualType()) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 646 | { |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 647 | data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); |
Greg Clayton | 3508c38 | 2012-02-24 01:59:29 +0000 | [diff] [blame] | 648 | Address address(addr, NULL); |
Greg Clayton | 567e7f3 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 649 | bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 650 | if (bytes_read == 0) |
| 651 | { |
Greg Clayton | 04e6ada | 2012-05-25 17:05:55 +0000 | [diff] [blame] | 652 | const char *error_cstr = error.AsCString(); |
| 653 | if (error_cstr && error_cstr[0]) |
| 654 | { |
| 655 | result.AppendError(error_cstr); |
| 656 | } |
| 657 | else |
| 658 | { |
| 659 | result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr); |
| 660 | } |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 661 | result.SetStatus(eReturnStatusFailed); |
| 662 | return false; |
| 663 | } |
| 664 | |
| 665 | if (bytes_read < total_byte_size) |
Jason Molenda | 7e5fa7f | 2011-09-20 21:44:10 +0000 | [diff] [blame] | 666 | result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr); |
Greg Clayton | 902b5be | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 667 | else |
| 668 | { |
| 669 | m_next_addr = addr + bytes_read; |
| 670 | m_prev_byte_size = bytes_read; |
| 671 | m_prev_format_options = m_format_options; |
| 672 | m_prev_memory_options = m_memory_options; |
| 673 | m_prev_outfile_options = m_outfile_options; |
| 674 | m_prev_varobj_options = m_varobj_options; |
| 675 | } |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 676 | } |
| 677 | |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 678 | StreamFile outfile_stream; |
| 679 | Stream *output_stream = NULL; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 680 | const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); |
| 681 | if (outfile_spec) |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 682 | { |
| 683 | char path[PATH_MAX]; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 684 | outfile_spec.GetPath (path, sizeof(path)); |
| 685 | |
| 686 | uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; |
| 687 | const bool append = m_outfile_options.GetAppend().GetCurrentValue(); |
| 688 | if (append) |
| 689 | open_options |= File::eOpenOptionAppend; |
| 690 | |
| 691 | if (outfile_stream.GetFile ().Open (path, open_options).Success()) |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 692 | { |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 693 | if (m_memory_options.m_output_as_binary) |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 694 | { |
| 695 | int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read); |
| 696 | if (bytes_written > 0) |
| 697 | { |
| 698 | result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", |
| 699 | bytes_written, |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 700 | append ? "appended" : "written", |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 701 | path); |
| 702 | return true; |
| 703 | } |
| 704 | else |
| 705 | { |
Greg Clayton | 851e30e | 2012-09-18 18:04:04 +0000 | [diff] [blame] | 706 | result.AppendErrorWithFormat("Failed to write %llu bytes to '%s'.\n", (uint64_t)bytes_read, path); |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 707 | result.SetStatus(eReturnStatusFailed); |
| 708 | return false; |
| 709 | } |
| 710 | } |
| 711 | else |
| 712 | { |
| 713 | // We are going to write ASCII to the file just point the |
| 714 | // output_stream to our outfile_stream... |
| 715 | output_stream = &outfile_stream; |
| 716 | } |
| 717 | } |
| 718 | else |
| 719 | { |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 720 | result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write"); |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 721 | result.SetStatus(eReturnStatusFailed); |
| 722 | return false; |
| 723 | } |
| 724 | } |
| 725 | else |
| 726 | { |
| 727 | output_stream = &result.GetOutputStream(); |
| 728 | } |
| 729 | |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 730 | |
Greg Clayton | 24a6bd9 | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 731 | ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 732 | if (clang_ast_type.GetOpaqueQualType()) |
| 733 | { |
| 734 | for (uint32_t i = 0; i<item_count; ++i) |
| 735 | { |
| 736 | addr_t item_addr = addr + (i * item_byte_size); |
Greg Clayton | 3508c38 | 2012-02-24 01:59:29 +0000 | [diff] [blame] | 737 | Address address (item_addr); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 738 | StreamString name_strm; |
| 739 | name_strm.Printf ("0x%llx", item_addr); |
Greg Clayton | 24a6bd9 | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 740 | ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope, |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 741 | name_strm.GetString().c_str(), |
| 742 | address, |
| 743 | clang_ast_type)); |
| 744 | if (valobj_sp) |
| 745 | { |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 746 | if (format != eFormatDefault) |
| 747 | valobj_sp->SetFormat (format); |
| 748 | |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 749 | bool scope_already_checked = true; |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 750 | |
Enrico Granata | 3069c62 | 2012-03-01 04:24:26 +0000 | [diff] [blame] | 751 | ValueObject::DumpValueObjectOptions options; |
| 752 | options.SetMaximumPointerDepth(m_varobj_options.ptr_depth) |
| 753 | .SetMaximumDepth(m_varobj_options.max_depth) |
| 754 | .SetShowLocation(m_varobj_options.show_location) |
| 755 | .SetShowTypes(m_varobj_options.show_types) |
| 756 | .SetUseObjectiveC(m_varobj_options.use_objc) |
| 757 | .SetScopeChecked(scope_already_checked) |
| 758 | .SetFlatOutput(m_varobj_options.flat_output) |
Enrico Granata | cf09f88 | 2012-03-19 22:58:49 +0000 | [diff] [blame] | 759 | .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth) |
Enrico Granata | 3069c62 | 2012-03-01 04:24:26 +0000 | [diff] [blame] | 760 | .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth) |
| 761 | .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap) |
| 762 | .SetFormat(format) |
| 763 | .SetSummary(); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 764 | ValueObject::DumpValueObject (*output_stream, |
| 765 | valobj_sp.get(), |
Enrico Granata | 3069c62 | 2012-03-01 04:24:26 +0000 | [diff] [blame] | 766 | options); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 767 | } |
| 768 | else |
| 769 | { |
| 770 | result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n", |
| 771 | view_as_type_cstr, |
| 772 | name_strm.GetString().c_str()); |
| 773 | result.SetStatus(eReturnStatusFailed); |
| 774 | return false; |
| 775 | } |
| 776 | } |
| 777 | return true; |
| 778 | } |
| 779 | |
| 780 | result.SetStatus(eReturnStatusSuccessFinishResult); |
| 781 | DataExtractor data (data_sp, |
Greg Clayton | 567e7f3 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 782 | target->GetArchitecture().GetByteOrder(), |
| 783 | target->GetArchitecture().GetAddressByteSize()); |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 784 | |
| 785 | |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 786 | assert (output_stream); |
Greg Clayton | 746979d | 2011-10-28 23:44:55 +0000 | [diff] [blame] | 787 | uint32_t bytes_dumped = data.Dump (output_stream, |
| 788 | 0, |
| 789 | m_format_options.GetFormat(), |
| 790 | item_byte_size, |
| 791 | item_count, |
| 792 | num_per_line, |
| 793 | addr, |
| 794 | 0, |
| 795 | 0, |
| 796 | exe_scope); |
| 797 | m_next_addr = addr + bytes_dumped; |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 798 | output_stream->EOL(); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 799 | return true; |
| 800 | } |
| 801 | |
Greg Clayton | 57b3c6b | 2011-04-27 22:04:39 +0000 | [diff] [blame] | 802 | OptionGroupOptions m_option_group; |
| 803 | OptionGroupFormat m_format_options; |
| 804 | OptionGroupReadMemory m_memory_options; |
| 805 | OptionGroupOutputFile m_outfile_options; |
Greg Clayton | 56bbdaf | 2011-04-28 20:55:26 +0000 | [diff] [blame] | 806 | OptionGroupValueObjectDisplay m_varobj_options; |
Greg Clayton | 902b5be | 2011-10-26 04:32:38 +0000 | [diff] [blame] | 807 | lldb::addr_t m_next_addr; |
| 808 | lldb::addr_t m_prev_byte_size; |
| 809 | OptionGroupFormat m_prev_format_options; |
| 810 | OptionGroupReadMemory m_prev_memory_options; |
| 811 | OptionGroupOutputFile m_prev_outfile_options; |
| 812 | OptionGroupValueObjectDisplay m_prev_varobj_options; |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 813 | }; |
| 814 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 815 | |
| 816 | OptionDefinition |
| 817 | g_memory_write_option_table[] = |
| 818 | { |
| 819 | { LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, |
| 820 | { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, |
| 821 | }; |
| 822 | |
| 823 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 824 | //---------------------------------------------------------------------- |
| 825 | // Write memory to the inferior process |
| 826 | //---------------------------------------------------------------------- |
Jim Ingham | da26bd2 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 827 | class CommandObjectMemoryWrite : public CommandObjectParsed |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 828 | { |
| 829 | public: |
| 830 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 831 | class OptionGroupWriteMemory : public OptionGroup |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 832 | { |
| 833 | public: |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 834 | OptionGroupWriteMemory () : |
| 835 | OptionGroup() |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 836 | { |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 837 | } |
| 838 | |
| 839 | virtual |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 840 | ~OptionGroupWriteMemory () |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 841 | { |
| 842 | } |
| 843 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 844 | virtual uint32_t |
| 845 | GetNumDefinitions () |
| 846 | { |
| 847 | return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); |
| 848 | } |
| 849 | |
| 850 | virtual const OptionDefinition* |
| 851 | GetDefinitions () |
| 852 | { |
| 853 | return g_memory_write_option_table; |
| 854 | } |
| 855 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 856 | virtual Error |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 857 | SetOptionValue (CommandInterpreter &interpreter, |
| 858 | uint32_t option_idx, |
| 859 | const char *option_arg) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 860 | { |
| 861 | Error error; |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 862 | char short_option = (char) g_memory_write_option_table[option_idx].short_option; |
| 863 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 864 | switch (short_option) |
| 865 | { |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 866 | case 'i': |
| 867 | m_infile.SetFile (option_arg, true); |
| 868 | if (!m_infile.Exists()) |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 869 | { |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 870 | m_infile.Clear(); |
Greg Clayton | 9c23673 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 871 | error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg); |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 872 | } |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 873 | break; |
| 874 | |
| 875 | case 'o': |
| 876 | { |
| 877 | bool success; |
| 878 | m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success); |
| 879 | if (!success) |
| 880 | { |
Greg Clayton | 9c23673 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 881 | error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 882 | } |
| 883 | } |
| 884 | break; |
| 885 | |
| 886 | default: |
Greg Clayton | 9c23673 | 2011-10-26 00:56:27 +0000 | [diff] [blame] | 887 | error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 888 | break; |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 889 | } |
| 890 | return error; |
| 891 | } |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 892 | |
| 893 | virtual void |
| 894 | OptionParsingStarting (CommandInterpreter &interpreter) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 895 | { |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 896 | m_infile.Clear(); |
| 897 | m_infile_offset = 0; |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 898 | } |
| 899 | |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 900 | FileSpec m_infile; |
| 901 | off_t m_infile_offset; |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 902 | }; |
| 903 | |
Greg Clayton | 238c0a1 | 2010-09-18 01:14:36 +0000 | [diff] [blame] | 904 | CommandObjectMemoryWrite (CommandInterpreter &interpreter) : |
Jim Ingham | da26bd2 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 905 | CommandObjectParsed (interpreter, |
| 906 | "memory write", |
| 907 | "Write to the memory of the process being debugged.", |
| 908 | NULL, |
| 909 | eFlagProcessMustBeLaunched), |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 910 | m_option_group (interpreter), |
| 911 | m_format_options (eFormatBytes, 1, UINT64_MAX), |
| 912 | m_memory_options () |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 913 | { |
Caroline Tice | 43b014a | 2010-10-04 22:28:36 +0000 | [diff] [blame] | 914 | CommandArgumentEntry arg1; |
| 915 | CommandArgumentEntry arg2; |
| 916 | CommandArgumentData addr_arg; |
| 917 | CommandArgumentData value_arg; |
| 918 | |
| 919 | // Define the first (and only) variant of this arg. |
| 920 | addr_arg.arg_type = eArgTypeAddress; |
| 921 | addr_arg.arg_repetition = eArgRepeatPlain; |
| 922 | |
| 923 | // There is only one variant this argument could be; put it into the argument entry. |
| 924 | arg1.push_back (addr_arg); |
| 925 | |
| 926 | // Define the first (and only) variant of this arg. |
| 927 | value_arg.arg_type = eArgTypeValue; |
| 928 | value_arg.arg_repetition = eArgRepeatPlus; |
| 929 | |
| 930 | // There is only one variant this argument could be; put it into the argument entry. |
| 931 | arg2.push_back (value_arg); |
| 932 | |
| 933 | // Push the data for the first argument into the m_arguments vector. |
| 934 | m_arguments.push_back (arg1); |
| 935 | m_arguments.push_back (arg2); |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 936 | |
| 937 | m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); |
| 938 | m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2); |
| 939 | m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2); |
| 940 | m_option_group.Finalize(); |
| 941 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 942 | } |
| 943 | |
| 944 | virtual |
| 945 | ~CommandObjectMemoryWrite () |
| 946 | { |
| 947 | } |
| 948 | |
| 949 | Options * |
| 950 | GetOptions () |
| 951 | { |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 952 | return &m_option_group; |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 953 | } |
| 954 | |
| 955 | bool |
| 956 | UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) |
| 957 | { |
| 958 | if (total_byte_size > 8) |
| 959 | return false; |
| 960 | |
| 961 | if (total_byte_size == 8) |
| 962 | return true; |
| 963 | |
| 964 | const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; |
| 965 | return uval64 <= max; |
| 966 | } |
| 967 | |
| 968 | bool |
| 969 | SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) |
| 970 | { |
| 971 | if (total_byte_size > 8) |
| 972 | return false; |
| 973 | |
| 974 | if (total_byte_size == 8) |
| 975 | return true; |
| 976 | |
| 977 | const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; |
| 978 | const int64_t min = ~(max); |
| 979 | return min <= sval64 && sval64 <= max; |
| 980 | } |
| 981 | |
Jim Ingham | da26bd2 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 982 | protected: |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 983 | virtual bool |
Jim Ingham | da26bd2 | 2012-06-08 21:56:10 +0000 | [diff] [blame] | 984 | DoExecute (Args& command, CommandReturnObject &result) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 985 | { |
Greg Clayton | 567e7f3 | 2011-09-22 04:58:26 +0000 | [diff] [blame] | 986 | Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 987 | if (process == NULL) |
| 988 | { |
| 989 | result.AppendError("need a process to read memory"); |
| 990 | result.SetStatus(eReturnStatusFailed); |
| 991 | return false; |
| 992 | } |
| 993 | |
| 994 | const size_t argc = command.GetArgumentCount(); |
| 995 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 996 | if (m_memory_options.m_infile) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 997 | { |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 998 | if (argc < 1) |
| 999 | { |
| 1000 | result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str()); |
| 1001 | result.SetStatus(eReturnStatusFailed); |
| 1002 | return false; |
| 1003 | } |
| 1004 | } |
| 1005 | else if (argc < 2) |
| 1006 | { |
| 1007 | result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str()); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1008 | result.SetStatus(eReturnStatusFailed); |
| 1009 | return false; |
| 1010 | } |
| 1011 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1012 | StreamString buffer (Stream::eBinary, |
Greg Clayton | 395fc33 | 2011-02-15 21:59:32 +0000 | [diff] [blame] | 1013 | process->GetTarget().GetArchitecture().GetAddressByteSize(), |
| 1014 | process->GetTarget().GetArchitecture().GetByteOrder()); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1015 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1016 | OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue(); |
| 1017 | size_t item_byte_size = byte_size_value.GetCurrentValue(); |
Greg Clayton | 54e7afa | 2010-07-09 20:39:50 +0000 | [diff] [blame] | 1018 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1019 | lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0); |
| 1020 | |
| 1021 | if (addr == LLDB_INVALID_ADDRESS) |
| 1022 | { |
| 1023 | result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0)); |
| 1024 | result.SetStatus(eReturnStatusFailed); |
| 1025 | return false; |
| 1026 | } |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1027 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1028 | if (m_memory_options.m_infile) |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1029 | { |
| 1030 | size_t length = SIZE_MAX; |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1031 | if (item_byte_size > 0) |
| 1032 | length = item_byte_size; |
| 1033 | lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1034 | if (data_sp) |
| 1035 | { |
| 1036 | length = data_sp->GetByteSize(); |
| 1037 | if (length > 0) |
| 1038 | { |
| 1039 | Error error; |
| 1040 | size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error); |
| 1041 | |
| 1042 | if (bytes_written == length) |
| 1043 | { |
| 1044 | // All bytes written |
Greg Clayton | 851e30e | 2012-09-18 18:04:04 +0000 | [diff] [blame] | 1045 | result.GetOutputStream().Printf("%llu bytes were written to 0x%llx\n", (uint64_t)bytes_written, addr); |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1046 | result.SetStatus(eReturnStatusSuccessFinishResult); |
| 1047 | } |
| 1048 | else if (bytes_written > 0) |
| 1049 | { |
| 1050 | // Some byte written |
Greg Clayton | 851e30e | 2012-09-18 18:04:04 +0000 | [diff] [blame] | 1051 | result.GetOutputStream().Printf("%llu bytes of %llu requested were written to 0x%llx\n", (uint64_t)bytes_written, (uint64_t)length, addr); |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1052 | result.SetStatus(eReturnStatusSuccessFinishResult); |
| 1053 | } |
| 1054 | else |
| 1055 | { |
| 1056 | result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); |
| 1057 | result.SetStatus(eReturnStatusFailed); |
| 1058 | } |
| 1059 | } |
| 1060 | } |
| 1061 | else |
| 1062 | { |
| 1063 | result.AppendErrorWithFormat ("Unable to read contents of file.\n"); |
| 1064 | result.SetStatus(eReturnStatusFailed); |
| 1065 | } |
| 1066 | return result.Succeeded(); |
| 1067 | } |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1068 | else if (item_byte_size == 0) |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1069 | { |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1070 | if (m_format_options.GetFormat() == eFormatPointer) |
Greg Clayton | e9f5fbd | 2010-10-10 20:52:20 +0000 | [diff] [blame] | 1071 | item_byte_size = buffer.GetAddressByteSize(); |
| 1072 | else |
| 1073 | item_byte_size = 1; |
| 1074 | } |
| 1075 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1076 | command.Shift(); // shift off the address argument |
| 1077 | uint64_t uval64; |
| 1078 | int64_t sval64; |
| 1079 | bool success = false; |
| 1080 | const uint32_t num_value_args = command.GetArgumentCount(); |
| 1081 | uint32_t i; |
| 1082 | for (i=0; i<num_value_args; ++i) |
| 1083 | { |
| 1084 | const char *value_str = command.GetArgumentAtIndex(i); |
| 1085 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1086 | switch (m_format_options.GetFormat()) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1087 | { |
Greg Clayton | 3182eff | 2011-06-23 21:22:24 +0000 | [diff] [blame] | 1088 | case kNumFormats: |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1089 | case eFormatFloat: // TODO: add support for floats soon |
| 1090 | case eFormatCharPrintable: |
| 1091 | case eFormatBytesWithASCII: |
| 1092 | case eFormatComplex: |
| 1093 | case eFormatEnum: |
| 1094 | case eFormatUnicode16: |
| 1095 | case eFormatUnicode32: |
| 1096 | case eFormatVectorOfChar: |
| 1097 | case eFormatVectorOfSInt8: |
| 1098 | case eFormatVectorOfUInt8: |
| 1099 | case eFormatVectorOfSInt16: |
| 1100 | case eFormatVectorOfUInt16: |
| 1101 | case eFormatVectorOfSInt32: |
| 1102 | case eFormatVectorOfUInt32: |
| 1103 | case eFormatVectorOfSInt64: |
| 1104 | case eFormatVectorOfUInt64: |
| 1105 | case eFormatVectorOfFloat32: |
| 1106 | case eFormatVectorOfFloat64: |
| 1107 | case eFormatVectorOfUInt128: |
Greg Clayton | 4fdf760 | 2011-03-20 04:57:14 +0000 | [diff] [blame] | 1108 | case eFormatOSType: |
| 1109 | case eFormatComplexInteger: |
Greg Clayton | 24a6bd9 | 2011-10-27 17:55:14 +0000 | [diff] [blame] | 1110 | case eFormatAddressInfo: |
| 1111 | case eFormatHexFloat: |
| 1112 | case eFormatInstruction: |
Sean Callanan | 96abc62 | 2012-08-08 17:35:10 +0000 | [diff] [blame] | 1113 | case eFormatVoid: |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1114 | result.AppendError("unsupported format for writing memory"); |
| 1115 | result.SetStatus(eReturnStatusFailed); |
| 1116 | return false; |
| 1117 | |
| 1118 | case eFormatDefault: |
| 1119 | case eFormatBytes: |
| 1120 | case eFormatHex: |
Enrico Granata | 535543d | 2012-08-09 19:33:34 +0000 | [diff] [blame] | 1121 | case eFormatHexUppercase: |
Greg Clayton | 54e7afa | 2010-07-09 20:39:50 +0000 | [diff] [blame] | 1122 | case eFormatPointer: |
| 1123 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1124 | // Decode hex bytes |
| 1125 | uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); |
| 1126 | if (!success) |
| 1127 | { |
| 1128 | result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); |
| 1129 | result.SetStatus(eReturnStatusFailed); |
| 1130 | return false; |
| 1131 | } |
| 1132 | else if (!UIntValueIsValidForSize (uval64, item_byte_size)) |
| 1133 | { |
Jason Molenda | 7e5fa7f | 2011-09-20 21:44:10 +0000 | [diff] [blame] | 1134 | result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1135 | result.SetStatus(eReturnStatusFailed); |
| 1136 | return false; |
| 1137 | } |
| 1138 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1139 | break; |
| 1140 | |
| 1141 | case eFormatBoolean: |
| 1142 | uval64 = Args::StringToBoolean(value_str, false, &success); |
| 1143 | if (!success) |
| 1144 | { |
| 1145 | result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str); |
| 1146 | result.SetStatus(eReturnStatusFailed); |
| 1147 | return false; |
| 1148 | } |
| 1149 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1150 | break; |
| 1151 | |
| 1152 | case eFormatBinary: |
| 1153 | uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); |
| 1154 | if (!success) |
| 1155 | { |
| 1156 | result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); |
| 1157 | result.SetStatus(eReturnStatusFailed); |
| 1158 | return false; |
| 1159 | } |
| 1160 | else if (!UIntValueIsValidForSize (uval64, item_byte_size)) |
| 1161 | { |
Jason Molenda | 7e5fa7f | 2011-09-20 21:44:10 +0000 | [diff] [blame] | 1162 | result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1163 | result.SetStatus(eReturnStatusFailed); |
| 1164 | return false; |
| 1165 | } |
| 1166 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1167 | break; |
| 1168 | |
Greg Clayton | 307fa07 | 2011-06-17 23:50:44 +0000 | [diff] [blame] | 1169 | case eFormatCharArray: |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1170 | case eFormatChar: |
| 1171 | case eFormatCString: |
| 1172 | if (value_str[0]) |
| 1173 | { |
| 1174 | size_t len = strlen (value_str); |
| 1175 | // Include the NULL for C strings... |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1176 | if (m_format_options.GetFormat() == eFormatCString) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1177 | ++len; |
| 1178 | Error error; |
| 1179 | if (process->WriteMemory (addr, value_str, len, error) == len) |
| 1180 | { |
| 1181 | addr += len; |
| 1182 | } |
| 1183 | else |
| 1184 | { |
| 1185 | result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); |
| 1186 | result.SetStatus(eReturnStatusFailed); |
| 1187 | return false; |
| 1188 | } |
| 1189 | } |
| 1190 | break; |
| 1191 | |
| 1192 | case eFormatDecimal: |
| 1193 | sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); |
| 1194 | if (!success) |
| 1195 | { |
| 1196 | result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); |
| 1197 | result.SetStatus(eReturnStatusFailed); |
| 1198 | return false; |
| 1199 | } |
| 1200 | else if (!SIntValueIsValidForSize (sval64, item_byte_size)) |
| 1201 | { |
Jason Molenda | 7e5fa7f | 2011-09-20 21:44:10 +0000 | [diff] [blame] | 1202 | result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1203 | result.SetStatus(eReturnStatusFailed); |
| 1204 | return false; |
| 1205 | } |
| 1206 | buffer.PutMaxHex64 (sval64, item_byte_size); |
| 1207 | break; |
| 1208 | |
| 1209 | case eFormatUnsigned: |
| 1210 | uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); |
| 1211 | if (!success) |
| 1212 | { |
| 1213 | result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); |
| 1214 | result.SetStatus(eReturnStatusFailed); |
| 1215 | return false; |
| 1216 | } |
| 1217 | else if (!UIntValueIsValidForSize (uval64, item_byte_size)) |
| 1218 | { |
Jason Molenda | 7e5fa7f | 2011-09-20 21:44:10 +0000 | [diff] [blame] | 1219 | result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1220 | result.SetStatus(eReturnStatusFailed); |
| 1221 | return false; |
| 1222 | } |
| 1223 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1224 | break; |
| 1225 | |
| 1226 | case eFormatOctal: |
| 1227 | uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); |
| 1228 | if (!success) |
| 1229 | { |
| 1230 | result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); |
| 1231 | result.SetStatus(eReturnStatusFailed); |
| 1232 | return false; |
| 1233 | } |
| 1234 | else if (!UIntValueIsValidForSize (uval64, item_byte_size)) |
| 1235 | { |
Jason Molenda | 7e5fa7f | 2011-09-20 21:44:10 +0000 | [diff] [blame] | 1236 | result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1237 | result.SetStatus(eReturnStatusFailed); |
| 1238 | return false; |
| 1239 | } |
| 1240 | buffer.PutMaxHex64 (uval64, item_byte_size); |
| 1241 | break; |
| 1242 | } |
| 1243 | } |
| 1244 | |
| 1245 | if (!buffer.GetString().empty()) |
| 1246 | { |
| 1247 | Error error; |
Greg Clayton | 53d68e7 | 2010-07-20 22:52:08 +0000 | [diff] [blame] | 1248 | if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size()) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1249 | return true; |
| 1250 | else |
| 1251 | { |
| 1252 | result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString()); |
| 1253 | result.SetStatus(eReturnStatusFailed); |
| 1254 | return false; |
| 1255 | } |
| 1256 | } |
| 1257 | return true; |
| 1258 | } |
| 1259 | |
Greg Clayton | a42880a | 2011-10-25 06:44:01 +0000 | [diff] [blame] | 1260 | OptionGroupOptions m_option_group; |
| 1261 | OptionGroupFormat m_format_options; |
| 1262 | OptionGroupWriteMemory m_memory_options; |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1263 | }; |
| 1264 | |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1265 | |
| 1266 | //------------------------------------------------------------------------- |
| 1267 | // CommandObjectMemory |
| 1268 | //------------------------------------------------------------------------- |
| 1269 | |
Greg Clayton | 63094e0 | 2010-06-23 01:19:29 +0000 | [diff] [blame] | 1270 | CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) : |
Greg Clayton | 238c0a1 | 2010-09-18 01:14:36 +0000 | [diff] [blame] | 1271 | CommandObjectMultiword (interpreter, |
| 1272 | "memory", |
Caroline Tice | c1ad82e | 2010-09-07 22:38:08 +0000 | [diff] [blame] | 1273 | "A set of commands for operating on memory.", |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1274 | "memory <subcommand> [<subcommand-options>]") |
| 1275 | { |
Greg Clayton | 238c0a1 | 2010-09-18 01:14:36 +0000 | [diff] [blame] | 1276 | LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter))); |
| 1277 | LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter))); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1278 | } |
| 1279 | |
| 1280 | CommandObjectMemory::~CommandObjectMemory () |
| 1281 | { |
| 1282 | } |