bool ValueObject::UpdateValueIfNeeded (ExecutionContextScope *exe_scope) { if (exe_scope) { Process *process = exe_scope->CalculateProcess(); if (process) { const user_id_t stop_id = process->GetStopID(); if (m_update_id != stop_id) { m_value_str.clear(); m_location_str.clear(); m_summary_str.clear(); UpdateValue (exe_scope); if (m_error.Success()) m_update_id = stop_id; } } } return m_error.Success(); }
void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() { // TODO: implement HashTableSignature... Process *process = GetProcess(); if (process) { // Update the process stop ID that indicates the last time we updated the // map, whether it was successful or not. m_isa_to_descriptor_stop_id = process->GetStopID(); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); ProcessSP process_sp = process->shared_from_this(); ModuleSP objc_module_sp(GetObjCModule()); if (!objc_module_sp) return; uint32_t isa_count = 0; lldb::addr_t hash_table_ptr = GetISAHashTablePointer (); if (hash_table_ptr != LLDB_INVALID_ADDRESS) { // Read the NXHashTable struct: // // typedef struct { // const NXHashTablePrototype *prototype; // unsigned count; // unsigned nbBuckets; // void *buckets; // const void *info; // } NXHashTable; Error error; DataBufferHeap buffer(1024, 0); if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) == 20) { const uint32_t addr_size = m_process->GetAddressByteSize(); const ByteOrder byte_order = m_process->GetByteOrder(); DataExtractor data (buffer.GetBytes(), buffer.GetByteSize(), byte_order, addr_size); lldb::offset_t offset = addr_size; // Skip prototype const uint32_t count = data.GetU32(&offset); const uint32_t num_buckets = data.GetU32(&offset); const addr_t buckets_ptr = data.GetPointer(&offset); if (m_hash_signature.NeedsUpdate (count, num_buckets, buckets_ptr)) { m_hash_signature.UpdateSignature (count, num_buckets, buckets_ptr); const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t); buffer.SetByteSize(data_size); if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size, error) == data_size) { data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order); offset = 0; for (uint32_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx) { const uint32_t bucket_isa_count = data.GetU32 (&offset); const lldb::addr_t bucket_data = data.GetU32 (&offset); if (bucket_isa_count == 0) continue; isa_count += bucket_isa_count; ObjCISA isa; if (bucket_isa_count == 1) { // When we only have one entry in the bucket, the bucket data is the "isa" isa = bucket_data; if (isa) { if (!ISAIsCached(isa)) { ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp)); if (log && log->GetVerbose()) log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa); AddClass (isa, descriptor_sp); } } } else { // When we have more than one entry in the bucket, the bucket data is a pointer // to an array of "isa" values addr_t isa_addr = bucket_data; for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count; ++isa_idx, isa_addr += addr_size) { isa = m_process->ReadPointerFromMemory(isa_addr, error); if (isa && isa != LLDB_INVALID_ADDRESS) { if (!ISAIsCached(isa)) { ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp)); if (log && log->GetVerbose()) log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa); AddClass (isa, descriptor_sp); } } } } } } } } } } else { m_isa_to_descriptor_stop_id = UINT32_MAX; } }