1 | //===-- Value.cpp ---------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/Core/Value.h" |
10 | |
11 | #include "lldb/Core/Address.h" |
12 | #include "lldb/Core/Module.h" |
13 | #include "lldb/Symbol/CompilerType.h" |
14 | #include "lldb/Symbol/ObjectFile.h" |
15 | #include "lldb/Symbol/SymbolContext.h" |
16 | #include "lldb/Symbol/Type.h" |
17 | #include "lldb/Symbol/Variable.h" |
18 | #include "lldb/Target/ExecutionContext.h" |
19 | #include "lldb/Target/Process.h" |
20 | #include "lldb/Target/SectionLoadList.h" |
21 | #include "lldb/Target/Target.h" |
22 | #include "lldb/Utility/ConstString.h" |
23 | #include "lldb/Utility/DataBufferHeap.h" |
24 | #include "lldb/Utility/DataExtractor.h" |
25 | #include "lldb/Utility/Endian.h" |
26 | #include "lldb/Utility/FileSpec.h" |
27 | #include "lldb/Utility/LLDBLog.h" |
28 | #include "lldb/Utility/Log.h" |
29 | #include "lldb/Utility/State.h" |
30 | #include "lldb/Utility/Stream.h" |
31 | #include "lldb/lldb-defines.h" |
32 | #include "lldb/lldb-forward.h" |
33 | #include "lldb/lldb-types.h" |
34 | |
35 | #include <memory> |
36 | #include <optional> |
37 | #include <string> |
38 | |
39 | #include <cinttypes> |
40 | |
41 | using namespace lldb; |
42 | using namespace lldb_private; |
43 | |
44 | Value::Value() : m_value(), m_compiler_type(), m_data_buffer() {} |
45 | |
46 | Value::Value(const Scalar &scalar) |
47 | : m_value(scalar), m_compiler_type(), m_data_buffer() {} |
48 | |
49 | Value::Value(const void *bytes, int len) |
50 | : m_value(), m_compiler_type(), m_value_type(ValueType::HostAddress), |
51 | m_data_buffer() { |
52 | SetBytes(bytes, len); |
53 | } |
54 | |
55 | Value::Value(const Value &v) |
56 | : m_value(v.m_value), m_compiler_type(v.m_compiler_type), |
57 | m_context(v.m_context), m_value_type(v.m_value_type), |
58 | m_context_type(v.m_context_type), m_data_buffer() { |
59 | const uintptr_t rhs_value = |
60 | (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS); |
61 | if ((rhs_value != 0) && |
62 | (rhs_value == (uintptr_t)v.m_data_buffer.GetBytes())) { |
63 | m_data_buffer.CopyData(src: v.m_data_buffer.GetBytes(), |
64 | src_len: v.m_data_buffer.GetByteSize()); |
65 | |
66 | m_value = (uintptr_t)m_data_buffer.GetBytes(); |
67 | } |
68 | } |
69 | |
70 | Value &Value::operator=(const Value &rhs) { |
71 | if (this != &rhs) { |
72 | m_value = rhs.m_value; |
73 | m_compiler_type = rhs.m_compiler_type; |
74 | m_context = rhs.m_context; |
75 | m_value_type = rhs.m_value_type; |
76 | m_context_type = rhs.m_context_type; |
77 | const uintptr_t rhs_value = |
78 | (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS); |
79 | if ((rhs_value != 0) && |
80 | (rhs_value == (uintptr_t)rhs.m_data_buffer.GetBytes())) { |
81 | m_data_buffer.CopyData(src: rhs.m_data_buffer.GetBytes(), |
82 | src_len: rhs.m_data_buffer.GetByteSize()); |
83 | |
84 | m_value = (uintptr_t)m_data_buffer.GetBytes(); |
85 | } |
86 | } |
87 | return *this; |
88 | } |
89 | |
90 | void Value::SetBytes(const void *bytes, int len) { |
91 | m_value_type = ValueType::HostAddress; |
92 | m_data_buffer.CopyData(src: bytes, src_len: len); |
93 | m_value = (uintptr_t)m_data_buffer.GetBytes(); |
94 | } |
95 | |
96 | void Value::AppendBytes(const void *bytes, int len) { |
97 | m_value_type = ValueType::HostAddress; |
98 | m_data_buffer.AppendData(src: bytes, src_len: len); |
99 | m_value = (uintptr_t)m_data_buffer.GetBytes(); |
100 | } |
101 | |
102 | void Value::Dump(Stream *strm) { |
103 | if (!strm) |
104 | return; |
105 | m_value.GetValue(s&: *strm, show_type: true); |
106 | strm->Printf(format: ", value_type = %s, context = %p, context_type = %s" , |
107 | Value::GetValueTypeAsCString(context_type: m_value_type), m_context, |
108 | Value::GetContextTypeAsCString(context_type: m_context_type)); |
109 | } |
110 | |
111 | Value::ValueType Value::GetValueType() const { return m_value_type; } |
112 | |
113 | AddressType Value::GetValueAddressType() const { |
114 | switch (m_value_type) { |
115 | case ValueType::Invalid: |
116 | case ValueType::Scalar: |
117 | break; |
118 | case ValueType::LoadAddress: |
119 | return eAddressTypeLoad; |
120 | case ValueType::FileAddress: |
121 | return eAddressTypeFile; |
122 | case ValueType::HostAddress: |
123 | return eAddressTypeHost; |
124 | } |
125 | return eAddressTypeInvalid; |
126 | } |
127 | |
128 | Value::ValueType Value::GetValueTypeFromAddressType(AddressType address_type) { |
129 | switch (address_type) { |
130 | case eAddressTypeFile: |
131 | return Value::ValueType::FileAddress; |
132 | case eAddressTypeLoad: |
133 | return Value::ValueType::LoadAddress; |
134 | case eAddressTypeHost: |
135 | return Value::ValueType::HostAddress; |
136 | case eAddressTypeInvalid: |
137 | return Value::ValueType::Invalid; |
138 | } |
139 | llvm_unreachable("Unexpected address type!" ); |
140 | } |
141 | |
142 | RegisterInfo *Value::GetRegisterInfo() const { |
143 | if (m_context_type == ContextType::RegisterInfo) |
144 | return static_cast<RegisterInfo *>(m_context); |
145 | return nullptr; |
146 | } |
147 | |
148 | Type *Value::GetType() { |
149 | if (m_context_type == ContextType::LLDBType) |
150 | return static_cast<Type *>(m_context); |
151 | return nullptr; |
152 | } |
153 | |
154 | size_t Value::AppendDataToHostBuffer(const Value &rhs) { |
155 | if (this == &rhs) |
156 | return 0; |
157 | |
158 | size_t curr_size = m_data_buffer.GetByteSize(); |
159 | Status error; |
160 | switch (rhs.GetValueType()) { |
161 | case ValueType::Invalid: |
162 | return 0; |
163 | case ValueType::Scalar: { |
164 | const size_t scalar_size = rhs.m_value.GetByteSize(); |
165 | if (scalar_size > 0) { |
166 | const size_t new_size = curr_size + scalar_size; |
167 | if (ResizeData(len: new_size) == new_size) { |
168 | rhs.m_value.GetAsMemoryData(dst: m_data_buffer.GetBytes() + curr_size, |
169 | dst_len: scalar_size, dst_byte_order: endian::InlHostByteOrder(), |
170 | error); |
171 | return scalar_size; |
172 | } |
173 | } |
174 | } break; |
175 | case ValueType::FileAddress: |
176 | case ValueType::LoadAddress: |
177 | case ValueType::HostAddress: { |
178 | const uint8_t *src = rhs.GetBuffer().GetBytes(); |
179 | const size_t src_len = rhs.GetBuffer().GetByteSize(); |
180 | if (src && src_len > 0) { |
181 | const size_t new_size = curr_size + src_len; |
182 | if (ResizeData(len: new_size) == new_size) { |
183 | ::memcpy(dest: m_data_buffer.GetBytes() + curr_size, src: src, n: src_len); |
184 | return src_len; |
185 | } |
186 | } |
187 | } break; |
188 | } |
189 | return 0; |
190 | } |
191 | |
192 | size_t Value::ResizeData(size_t len) { |
193 | m_value_type = ValueType::HostAddress; |
194 | m_data_buffer.SetByteSize(len); |
195 | m_value = (uintptr_t)m_data_buffer.GetBytes(); |
196 | return m_data_buffer.GetByteSize(); |
197 | } |
198 | |
199 | bool Value::ValueOf(ExecutionContext *exe_ctx) { |
200 | switch (m_context_type) { |
201 | case ContextType::Invalid: |
202 | case ContextType::RegisterInfo: // RegisterInfo * |
203 | case ContextType::LLDBType: // Type * |
204 | break; |
205 | |
206 | case ContextType::Variable: // Variable * |
207 | ResolveValue(exe_ctx); |
208 | return true; |
209 | } |
210 | return false; |
211 | } |
212 | |
213 | uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) { |
214 | switch (m_context_type) { |
215 | case ContextType::RegisterInfo: // RegisterInfo * |
216 | if (GetRegisterInfo()) { |
217 | if (error_ptr) |
218 | error_ptr->Clear(); |
219 | return GetRegisterInfo()->byte_size; |
220 | } |
221 | break; |
222 | |
223 | case ContextType::Invalid: |
224 | case ContextType::LLDBType: // Type * |
225 | case ContextType::Variable: // Variable * |
226 | { |
227 | auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; |
228 | auto size_or_err = GetCompilerType().GetByteSize(exe_scope: scope); |
229 | if (!size_or_err) { |
230 | if (error_ptr && error_ptr->Success()) |
231 | *error_ptr = Status::FromError(error: size_or_err.takeError()); |
232 | else |
233 | LLDB_LOG_ERRORV(GetLog(LLDBLog::Types), size_or_err.takeError(), "{0}" ); |
234 | } else { |
235 | if (error_ptr) |
236 | error_ptr->Clear(); |
237 | return *size_or_err; |
238 | } |
239 | break; |
240 | } |
241 | } |
242 | if (error_ptr && error_ptr->Success()) |
243 | *error_ptr = Status::FromErrorString(str: "Unable to determine byte size." ); |
244 | return 0; |
245 | } |
246 | |
247 | const CompilerType &Value::GetCompilerType() { |
248 | if (!m_compiler_type.IsValid()) { |
249 | switch (m_context_type) { |
250 | case ContextType::Invalid: |
251 | break; |
252 | |
253 | case ContextType::RegisterInfo: |
254 | break; // TODO: Eventually convert into a compiler type? |
255 | |
256 | case ContextType::LLDBType: { |
257 | Type *lldb_type = GetType(); |
258 | if (lldb_type) |
259 | m_compiler_type = lldb_type->GetForwardCompilerType(); |
260 | } break; |
261 | |
262 | case ContextType::Variable: { |
263 | Variable *variable = GetVariable(); |
264 | if (variable) { |
265 | Type *variable_type = variable->GetType(); |
266 | if (variable_type) |
267 | m_compiler_type = variable_type->GetForwardCompilerType(); |
268 | } |
269 | } break; |
270 | } |
271 | } |
272 | |
273 | return m_compiler_type; |
274 | } |
275 | |
276 | void Value::SetCompilerType(const CompilerType &compiler_type) { |
277 | m_compiler_type = compiler_type; |
278 | } |
279 | |
280 | lldb::Format Value::GetValueDefaultFormat() { |
281 | switch (m_context_type) { |
282 | case ContextType::RegisterInfo: |
283 | if (GetRegisterInfo()) |
284 | return GetRegisterInfo()->format; |
285 | break; |
286 | |
287 | case ContextType::Invalid: |
288 | case ContextType::LLDBType: |
289 | case ContextType::Variable: { |
290 | const CompilerType &ast_type = GetCompilerType(); |
291 | if (ast_type.IsValid()) |
292 | return ast_type.GetFormat(); |
293 | } break; |
294 | } |
295 | |
296 | // Return a good default in case we can't figure anything out |
297 | return eFormatHex; |
298 | } |
299 | |
300 | bool Value::(DataExtractor &data) { |
301 | switch (m_value_type) { |
302 | case ValueType::Invalid: |
303 | return false; |
304 | case ValueType::Scalar: |
305 | if (m_value.GetData(data)) |
306 | return true; |
307 | break; |
308 | |
309 | case ValueType::LoadAddress: |
310 | case ValueType::FileAddress: |
311 | case ValueType::HostAddress: |
312 | if (m_data_buffer.GetByteSize()) { |
313 | data.SetData(bytes: m_data_buffer.GetBytes(), length: m_data_buffer.GetByteSize(), |
314 | byte_order: data.GetByteOrder()); |
315 | return true; |
316 | } |
317 | break; |
318 | } |
319 | |
320 | return false; |
321 | } |
322 | |
323 | Status Value::(ExecutionContext *exe_ctx, DataExtractor &data, |
324 | Module *module) { |
325 | data.Clear(); |
326 | |
327 | Status error; |
328 | lldb::addr_t address = LLDB_INVALID_ADDRESS; |
329 | AddressType address_type = eAddressTypeFile; |
330 | Address file_so_addr; |
331 | const CompilerType &ast_type = GetCompilerType(); |
332 | std::optional<uint64_t> type_size = |
333 | llvm::expectedToOptional(E: ast_type.GetByteSize( |
334 | exe_scope: exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr)); |
335 | // Nothing to be done for a zero-sized type. |
336 | if (type_size && *type_size == 0) |
337 | return error; |
338 | |
339 | switch (m_value_type) { |
340 | case ValueType::Invalid: |
341 | error = Status::FromErrorString(str: "invalid value" ); |
342 | break; |
343 | case ValueType::Scalar: { |
344 | data.SetByteOrder(endian::InlHostByteOrder()); |
345 | if (ast_type.IsValid()) |
346 | data.SetAddressByteSize(ast_type.GetPointerByteSize()); |
347 | else |
348 | data.SetAddressByteSize(sizeof(void *)); |
349 | |
350 | uint32_t limit_byte_size = UINT32_MAX; |
351 | |
352 | if (type_size) |
353 | limit_byte_size = *type_size; |
354 | |
355 | if (limit_byte_size <= m_value.GetByteSize()) { |
356 | if (m_value.GetData(data, limit_byte_size)) |
357 | return error; // Success; |
358 | } |
359 | |
360 | error = Status::FromErrorString(str: "extracting data from value failed" ); |
361 | break; |
362 | } |
363 | case ValueType::LoadAddress: |
364 | if (exe_ctx == nullptr) { |
365 | error = Status::FromErrorString( |
366 | str: "can't read load address (no execution context)" ); |
367 | } else { |
368 | Process *process = exe_ctx->GetProcessPtr(); |
369 | if (process == nullptr || !process->IsAlive()) { |
370 | Target *target = exe_ctx->GetTargetPtr(); |
371 | if (target) { |
372 | // Allow expressions to run and evaluate things when the target has |
373 | // memory sections loaded. This allows you to use "target modules |
374 | // load" to load your executable and any shared libraries, then |
375 | // execute commands where you can look at types in data sections. |
376 | if (target->HasLoadedSections()) { |
377 | address = m_value.ULongLong(LLDB_INVALID_ADDRESS); |
378 | if (target->ResolveLoadAddress(load_addr: address, so_addr&: file_so_addr)) { |
379 | address_type = eAddressTypeLoad; |
380 | data.SetByteOrder(target->GetArchitecture().GetByteOrder()); |
381 | data.SetAddressByteSize( |
382 | target->GetArchitecture().GetAddressByteSize()); |
383 | } else |
384 | address = LLDB_INVALID_ADDRESS; |
385 | } |
386 | } else { |
387 | error = Status::FromErrorString( |
388 | str: "can't read load address (invalid process)" ); |
389 | } |
390 | } else { |
391 | address = m_value.ULongLong(LLDB_INVALID_ADDRESS); |
392 | address_type = eAddressTypeLoad; |
393 | data.SetByteOrder( |
394 | process->GetTarget().GetArchitecture().GetByteOrder()); |
395 | data.SetAddressByteSize( |
396 | process->GetTarget().GetArchitecture().GetAddressByteSize()); |
397 | } |
398 | } |
399 | break; |
400 | |
401 | case ValueType::FileAddress: |
402 | if (exe_ctx == nullptr) { |
403 | error = Status::FromErrorString( |
404 | str: "can't read file address (no execution context)" ); |
405 | } else if (exe_ctx->GetTargetPtr() == nullptr) { |
406 | error = |
407 | Status::FromErrorString(str: "can't read file address (invalid target)" ); |
408 | } else { |
409 | address = m_value.ULongLong(LLDB_INVALID_ADDRESS); |
410 | if (address == LLDB_INVALID_ADDRESS) { |
411 | error = Status::FromErrorString(str: "invalid file address" ); |
412 | } else { |
413 | if (module == nullptr) { |
414 | // The only thing we can currently lock down to a module so that we |
415 | // can resolve a file address, is a variable. |
416 | Variable *variable = GetVariable(); |
417 | if (variable) { |
418 | SymbolContext var_sc; |
419 | variable->CalculateSymbolContext(sc: &var_sc); |
420 | module = var_sc.module_sp.get(); |
421 | } |
422 | } |
423 | |
424 | if (module) { |
425 | bool resolved = false; |
426 | ObjectFile *objfile = module->GetObjectFile(); |
427 | if (objfile) { |
428 | Address so_addr(address, objfile->GetSectionList()); |
429 | addr_t load_address = |
430 | so_addr.GetLoadAddress(target: exe_ctx->GetTargetPtr()); |
431 | bool process_launched_and_stopped = |
432 | exe_ctx->GetProcessPtr() |
433 | ? StateIsStoppedState(state: exe_ctx->GetProcessPtr()->GetState(), |
434 | must_exist: true /* must_exist */) |
435 | : false; |
436 | // Don't use the load address if the process has exited. |
437 | if (load_address != LLDB_INVALID_ADDRESS && |
438 | process_launched_and_stopped) { |
439 | resolved = true; |
440 | address = load_address; |
441 | address_type = eAddressTypeLoad; |
442 | data.SetByteOrder( |
443 | exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder()); |
444 | data.SetAddressByteSize(exe_ctx->GetTargetRef() |
445 | .GetArchitecture() |
446 | .GetAddressByteSize()); |
447 | } else { |
448 | if (so_addr.IsSectionOffset()) { |
449 | resolved = true; |
450 | file_so_addr = so_addr; |
451 | data.SetByteOrder(objfile->GetByteOrder()); |
452 | data.SetAddressByteSize(objfile->GetAddressByteSize()); |
453 | } |
454 | } |
455 | } |
456 | if (!resolved) { |
457 | Variable *variable = GetVariable(); |
458 | |
459 | if (module) { |
460 | if (variable) |
461 | error = Status::FromErrorStringWithFormat( |
462 | format: "unable to resolve the module for file address 0x%" PRIx64 |
463 | " for variable '%s' in %s" , |
464 | address, variable->GetName().AsCString(value_if_empty: "" ), |
465 | module->GetFileSpec().GetPath().c_str()); |
466 | else |
467 | error = Status::FromErrorStringWithFormat( |
468 | format: "unable to resolve the module for file address 0x%" PRIx64 |
469 | " in %s" , |
470 | address, module->GetFileSpec().GetPath().c_str()); |
471 | } else { |
472 | if (variable) |
473 | error = Status::FromErrorStringWithFormat( |
474 | format: "unable to resolve the module for file address 0x%" PRIx64 |
475 | " for variable '%s'" , |
476 | address, variable->GetName().AsCString(value_if_empty: "" )); |
477 | else |
478 | error = Status::FromErrorStringWithFormat( |
479 | format: "unable to resolve the module for file address 0x%" PRIx64, |
480 | address); |
481 | } |
482 | } |
483 | } else { |
484 | // Can't convert a file address to anything valid without more |
485 | // context (which Module it came from) |
486 | error = Status::FromErrorString( |
487 | str: "can't read memory from file address without more context" ); |
488 | } |
489 | } |
490 | } |
491 | break; |
492 | |
493 | case ValueType::HostAddress: |
494 | address = m_value.ULongLong(LLDB_INVALID_ADDRESS); |
495 | address_type = eAddressTypeHost; |
496 | if (exe_ctx) { |
497 | Target *target = exe_ctx->GetTargetPtr(); |
498 | if (target) { |
499 | data.SetByteOrder(target->GetArchitecture().GetByteOrder()); |
500 | data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); |
501 | break; |
502 | } |
503 | } |
504 | // fallback to host settings |
505 | data.SetByteOrder(endian::InlHostByteOrder()); |
506 | data.SetAddressByteSize(sizeof(void *)); |
507 | break; |
508 | } |
509 | |
510 | // Bail if we encountered any errors |
511 | if (error.Fail()) |
512 | return error; |
513 | |
514 | if (address == LLDB_INVALID_ADDRESS) { |
515 | error = Status::FromErrorStringWithFormat( |
516 | format: "invalid %s address" , |
517 | address_type == eAddressTypeHost ? "host" : "load" ); |
518 | return error; |
519 | } |
520 | |
521 | // If we got here, we need to read the value from memory. |
522 | size_t byte_size = GetValueByteSize(error_ptr: &error, exe_ctx); |
523 | |
524 | // Bail if we encountered any errors getting the byte size. |
525 | if (error.Fail()) |
526 | return error; |
527 | |
528 | // No memory to read for zero-sized types. |
529 | if (byte_size == 0) |
530 | return error; |
531 | |
532 | // Make sure we have enough room within "data", and if we don't make |
533 | // something large enough that does |
534 | if (!data.ValidOffsetForDataOfSize(offset: 0, length: byte_size)) { |
535 | auto data_sp = std::make_shared<DataBufferHeap>(args&: byte_size, args: '\0'); |
536 | data.SetData(data_sp); |
537 | } |
538 | |
539 | uint8_t *dst = const_cast<uint8_t *>(data.PeekData(offset: 0, length: byte_size)); |
540 | if (dst != nullptr) { |
541 | if (address_type == eAddressTypeHost) { |
542 | // The address is an address in this process, so just copy it. |
543 | if (address == 0) { |
544 | error = |
545 | Status::FromErrorString(str: "trying to read from host address of 0." ); |
546 | return error; |
547 | } |
548 | memcpy(dest: dst, src: reinterpret_cast<uint8_t *>(address), n: byte_size); |
549 | } else if ((address_type == eAddressTypeLoad) || |
550 | (address_type == eAddressTypeFile)) { |
551 | if (file_so_addr.IsValid()) { |
552 | const bool force_live_memory = true; |
553 | if (exe_ctx->GetTargetRef().ReadMemory(addr: file_so_addr, dst, dst_len: byte_size, |
554 | error, force_live_memory) != |
555 | byte_size) { |
556 | error = Status::FromErrorStringWithFormat( |
557 | format: "read memory from 0x%" PRIx64 " failed" , (uint64_t)address); |
558 | } |
559 | } else { |
560 | // The execution context might have a NULL process, but it might have a |
561 | // valid process in the exe_ctx->target, so use the |
562 | // ExecutionContext::GetProcess accessor to ensure we get the process |
563 | // if there is one. |
564 | Process *process = exe_ctx->GetProcessPtr(); |
565 | |
566 | if (process) { |
567 | const size_t bytes_read = |
568 | process->ReadMemory(vm_addr: address, buf: dst, size: byte_size, error); |
569 | if (bytes_read != byte_size) |
570 | error = Status::FromErrorStringWithFormat( |
571 | format: "read memory from 0x%" PRIx64 " failed (%u of %u bytes read)" , |
572 | (uint64_t)address, (uint32_t)bytes_read, (uint32_t)byte_size); |
573 | } else { |
574 | error = Status::FromErrorStringWithFormat( |
575 | format: "read memory from 0x%" PRIx64 " failed (invalid process)" , |
576 | (uint64_t)address); |
577 | } |
578 | } |
579 | } else { |
580 | error = Status::FromErrorStringWithFormat( |
581 | format: "unsupported AddressType value (%i)" , address_type); |
582 | } |
583 | } else { |
584 | error = Status::FromErrorString(str: "out of memory" ); |
585 | } |
586 | |
587 | return error; |
588 | } |
589 | |
590 | Scalar &Value::ResolveValue(ExecutionContext *exe_ctx, Module *module) { |
591 | const CompilerType &compiler_type = GetCompilerType(); |
592 | if (compiler_type.IsValid()) { |
593 | switch (m_value_type) { |
594 | case ValueType::Invalid: |
595 | case ValueType::Scalar: // raw scalar value |
596 | break; |
597 | |
598 | case ValueType::FileAddress: |
599 | case ValueType::LoadAddress: // load address value |
600 | case ValueType::HostAddress: // host address value (for memory in the process |
601 | // that is using liblldb) |
602 | { |
603 | DataExtractor data; |
604 | lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); |
605 | Status error(GetValueAsData(exe_ctx, data, module)); |
606 | if (error.Success()) { |
607 | Scalar scalar; |
608 | if (compiler_type.GetValueAsScalar( |
609 | data, data_offset: 0, data_byte_size: data.GetByteSize(), value&: scalar, |
610 | exe_scope: exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr)) { |
611 | m_value = scalar; |
612 | m_value_type = ValueType::Scalar; |
613 | } else { |
614 | if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) { |
615 | m_value.Clear(); |
616 | m_value_type = ValueType::Scalar; |
617 | } |
618 | } |
619 | } else { |
620 | if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) { |
621 | m_value.Clear(); |
622 | m_value_type = ValueType::Scalar; |
623 | } |
624 | } |
625 | } break; |
626 | } |
627 | } |
628 | return m_value; |
629 | } |
630 | |
631 | Variable *Value::GetVariable() { |
632 | if (m_context_type == ContextType::Variable) |
633 | return static_cast<Variable *>(m_context); |
634 | return nullptr; |
635 | } |
636 | |
637 | void Value::Clear() { |
638 | m_value.Clear(); |
639 | m_compiler_type.Clear(); |
640 | m_value_type = ValueType::Scalar; |
641 | m_context = nullptr; |
642 | m_context_type = ContextType::Invalid; |
643 | m_data_buffer.Clear(); |
644 | } |
645 | |
646 | const char *Value::GetValueTypeAsCString(ValueType value_type) { |
647 | switch (value_type) { |
648 | case ValueType::Invalid: |
649 | return "invalid" ; |
650 | case ValueType::Scalar: |
651 | return "scalar" ; |
652 | case ValueType::FileAddress: |
653 | return "file address" ; |
654 | case ValueType::LoadAddress: |
655 | return "load address" ; |
656 | case ValueType::HostAddress: |
657 | return "host address" ; |
658 | }; |
659 | llvm_unreachable("enum cases exhausted." ); |
660 | } |
661 | |
662 | const char *Value::GetContextTypeAsCString(ContextType context_type) { |
663 | switch (context_type) { |
664 | case ContextType::Invalid: |
665 | return "invalid" ; |
666 | case ContextType::RegisterInfo: |
667 | return "RegisterInfo *" ; |
668 | case ContextType::LLDBType: |
669 | return "Type *" ; |
670 | case ContextType::Variable: |
671 | return "Variable *" ; |
672 | }; |
673 | llvm_unreachable("enum cases exhausted." ); |
674 | } |
675 | |
676 | void Value::ConvertToLoadAddress(Module *module, Target *target) { |
677 | if (!module || !target || (GetValueType() != ValueType::FileAddress)) |
678 | return; |
679 | |
680 | lldb::addr_t file_addr = GetScalar().ULongLong(LLDB_INVALID_ADDRESS); |
681 | if (file_addr == LLDB_INVALID_ADDRESS) |
682 | return; |
683 | |
684 | Address so_addr; |
685 | if (!module->ResolveFileAddress(vm_addr: file_addr, so_addr)) |
686 | return; |
687 | lldb::addr_t load_addr = so_addr.GetLoadAddress(target); |
688 | if (load_addr == LLDB_INVALID_ADDRESS) |
689 | return; |
690 | |
691 | SetValueType(Value::ValueType::LoadAddress); |
692 | GetScalar() = load_addr; |
693 | } |
694 | |
695 | void ValueList::PushValue(const Value &value) { m_values.push_back(x: value); } |
696 | |
697 | size_t ValueList::GetSize() { return m_values.size(); } |
698 | |
699 | Value *ValueList::GetValueAtIndex(size_t idx) { |
700 | if (idx < GetSize()) { |
701 | return &(m_values[idx]); |
702 | } else |
703 | return nullptr; |
704 | } |
705 | |
706 | void ValueList::Clear() { m_values.clear(); } |
707 | |