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