bool AllocatedMemoryCache::DeallocateMemory (lldb::addr_t addr) { Mutex::Locker locker (m_mutex); PermissionsToBlockMap::iterator pos, end = m_memory_map.end(); bool success = false; for (pos = m_memory_map.begin(); pos != end; ++pos) { if (pos->second->Contains (addr)) { success = pos->second->FreeBlock (addr); break; } } LogSP log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); if (log) log->Printf("AllocatedMemoryCache::DeallocateMemory (addr = 0x%16.16llx) => %i", (uint64_t)addr, success); return success; }
void POSIXThread::Notify(const ProcessMessage &message) { LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); if (log) log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); switch (message.GetKind()) { default: assert(false && "Unexpected message kind!"); break; case ProcessMessage::eLimboMessage: LimboNotify(message); break; case ProcessMessage::eSignalMessage: SignalNotify(message); break; case ProcessMessage::eSignalDeliveredMessage: SignalDeliveredNotify(message); break; case ProcessMessage::eTraceMessage: TraceNotify(message); break; case ProcessMessage::eBreakpointMessage: BreakNotify(message); break; case ProcessMessage::eCrashMessage: CrashNotify(message); break; } }
lldb::RegisterContextSP POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) { lldb::RegisterContextSP reg_ctx_sp; uint32_t concrete_frame_idx = 0; LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) log->Printf ("POSIXThread::%s ()", __FUNCTION__); if (frame) concrete_frame_idx = frame->GetConcreteFrameIndex(); if (concrete_frame_idx == 0) reg_ctx_sp = GetRegisterContext(); else { assert(GetUnwinder()); reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); } return reg_ctx_sp; }
void ModuleList::LogUUIDAndPaths (LogSP &log_sp, const char *prefix_cstr) { if (log_sp) { Mutex::Locker locker(m_modules_mutex); char uuid_cstr[256]; collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end(); for (pos = begin; pos != end; ++pos) { Module *module = pos->get(); module->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr)); const FileSpec &module_file_spec = module->GetFileSpec(); log_sp->Printf ("%s[%u] %s (%s) \"%s/%s\"", prefix_cstr ? prefix_cstr : "", (uint32_t)std::distance (begin, pos), uuid_cstr, module->GetArchitecture().GetArchitectureName(), module_file_spec.GetDirectory().GetCString(), module_file_spec.GetFilename().GetCString()); } } }
bool DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) { Timer scoped_timer (__PRETTY_FUNCTION__, "DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data); LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES)); if (log) log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data); m_sets.clear(); DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo(); if (debug_info) { const DataExtractor* debug_str = &dwarf2Data->get_debug_str_data(); uint32_t cu_idx = 0; const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize()); bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1; DWARFDIECollection dies; const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_subprogram, dies) + cu->AppendDIEsWithTag (DW_TAG_variable, dies); dw_offset_t cu_offset = cu->GetOffset(); DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset); size_t die_idx; for (die_idx = 0; die_idx < die_count; ++die_idx) { const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx); DWARFDebugInfoEntry::Attributes attributes; const char *name = NULL; const char *mangled = NULL; bool add_die = false; bool is_variable = false; const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes); if (num_attributes > 0) { uint32_t i; dw_tag_t tag = die->Tag(); is_variable = tag == DW_TAG_variable; for (i=0; i<num_attributes; ++i) { dw_attr_t attr = attributes.AttributeAtIndex(i); DWARFFormValue form_value; switch (attr) { case DW_AT_name: if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) name = form_value.AsCString(debug_str); break; case DW_AT_MIPS_linkage_name: if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) mangled = form_value.AsCString(debug_str); break; case DW_AT_low_pc: case DW_AT_ranges: case DW_AT_entry_pc: if (tag == DW_TAG_subprogram) add_die = true; break; case DW_AT_location: if (tag == DW_TAG_variable) { const DWARFDebugInfoEntry* parent_die = die->GetParent(); while ( parent_die != NULL ) { switch (parent_die->Tag()) { case DW_TAG_subprogram: case DW_TAG_lexical_block: case DW_TAG_inlined_subroutine: // Even if this is a function level static, we don't add it. We could theoretically // add these if we wanted to by introspecting into the DW_AT_location and seeing // if the location describes a hard coded address, but we don't want the performance // penalty of that right now. add_die = false; // if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) // { // // If we have valid block data, then we have location expression bytes // // that are fixed (not a location list). // const uint8_t *block_data = form_value.BlockData(); // if (block_data) // { // uint32_t block_length = form_value.Unsigned(); // if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) // { // if (block_data[0] == DW_OP_addr) // add_die = true; // } // } // } parent_die = NULL; // Terminate the while loop. break; case DW_TAG_compile_unit: add_die = true; parent_die = NULL; // Terminate the while loop. break; default: parent_die = parent_die->GetParent(); // Keep going in the while loop. break; } } } break; } } } if (add_die && (name || mangled)) { pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name); } } if (pubnames_set.NumDescriptors() > 0) { m_sets.push_back(pubnames_set); } // Keep memory down by clearing DIEs if this generate function // caused them to be parsed if (clear_dies) cu->ClearDIEs (true); } } if (m_sets.empty()) return false; if (log) Dump (log.get()); return true; }
void Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_locations) { Mutex::Locker modules_mutex(module_list.GetMutex()); if (load) { // The logic for handling new modules is: // 1) If the filter rejects this module, then skip it. // 2) Run through the current location list and if there are any locations // for that module, we mark the module as "seen" and we don't try to re-resolve // breakpoint locations for that module. // However, we do add breakpoint sites to these locations if needed. // 3) If we don't see this module in our breakpoint location list, call ResolveInModules. ModuleList new_modules; // We'll stuff the "unseen" modules in this list, and then resolve // them after the locations pass. Have to do it this way because // resolving breakpoints will add new locations potentially. const size_t num_locs = m_locations.GetSize(); size_t num_modules = module_list.GetSize(); for (size_t i = 0; i < num_modules; i++) { bool seen = false; ModuleSP module_sp (module_list.GetModuleAtIndexUnlocked (i)); if (!m_filter_sp->ModulePasses (module_sp)) continue; for (size_t loc_idx = 0; loc_idx < num_locs; loc_idx++) { BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx); if (!break_loc->IsEnabled()) continue; SectionSP section_sp (break_loc->GetAddress().GetSection()); if (!section_sp || section_sp->GetModule() == module_sp) { if (!seen) seen = true; if (!break_loc->ResolveBreakpointSite()) { LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); if (log) log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n", break_loc->GetID(), GetID()); } } } if (!seen) new_modules.AppendIfNeeded (module_sp); } if (new_modules.GetSize() > 0) { // If this is not an internal breakpoint, set up to record the new locations, then dispatch // an event with the new locations. if (!IsInternal()) { BreakpointEventData *new_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsAdded, shared_from_this()); m_locations.StartRecordingNewLocations(new_locations_event->GetBreakpointLocationCollection()); ResolveBreakpointInModules(new_modules); m_locations.StopRecordingNewLocations(); if (new_locations_event->GetBreakpointLocationCollection().GetSize() != 0) { SendBreakpointChangedEvent (new_locations_event); } else delete new_locations_event; } else ResolveBreakpointInModules(new_modules); } } else { // Go through the currently set locations and if any have breakpoints in // the module list, then remove their breakpoint sites, and their locations if asked to. BreakpointEventData *removed_locations_event; if (!IsInternal()) removed_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsRemoved, shared_from_this()); else removed_locations_event = NULL; size_t num_modules = module_list.GetSize(); for (size_t i = 0; i < num_modules; i++) { ModuleSP module_sp (module_list.GetModuleAtIndexUnlocked (i)); if (m_filter_sp->ModulePasses (module_sp)) { size_t loc_idx = 0; size_t num_locations = m_locations.GetSize(); BreakpointLocationCollection locations_to_remove; for (loc_idx = 0; loc_idx < num_locations; loc_idx++) { BreakpointLocationSP break_loc_sp (m_locations.GetByIndex(loc_idx)); SectionSP section_sp (break_loc_sp->GetAddress().GetSection()); if (section_sp && section_sp->GetModule() == module_sp) { // Remove this breakpoint since the shared library is // unloaded, but keep the breakpoint location around // so we always get complete hit count and breakpoint // lifetime info break_loc_sp->ClearBreakpointSite(); if (removed_locations_event) { removed_locations_event->GetBreakpointLocationCollection().Add(break_loc_sp); } if (delete_locations) locations_to_remove.Add (break_loc_sp); } } if (delete_locations) { size_t num_locations_to_remove = locations_to_remove.GetSize(); for (loc_idx = 0; loc_idx < num_locations_to_remove; loc_idx++) m_locations.RemoveLocation (locations_to_remove.GetByIndex(loc_idx)); } } } SendBreakpointChangedEvent (removed_locations_event); } }
lldb::addr_t AllocatedBlock::ReserveBlock (uint32_t size) { addr_t addr = LLDB_INVALID_ADDRESS; if (size <= m_byte_size) { const uint32_t needed_chunks = CalculateChunksNeededForSize (size); LogSP log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (m_offset_to_chunk_size.empty()) { m_offset_to_chunk_size[0] = needed_chunks; if (log) log->Printf ("[1] AllocatedBlock::ReserveBlock (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", size, size, 0, needed_chunks, m_chunk_size); addr = m_addr; } else { uint32_t last_offset = 0; OffsetToChunkSize::const_iterator pos = m_offset_to_chunk_size.begin(); OffsetToChunkSize::const_iterator end = m_offset_to_chunk_size.end(); while (pos != end) { if (pos->first > last_offset) { const uint32_t bytes_available = pos->first - last_offset; const uint32_t num_chunks = CalculateChunksNeededForSize (bytes_available); if (num_chunks >= needed_chunks) { m_offset_to_chunk_size[last_offset] = needed_chunks; if (log) log->Printf ("[2] AllocatedBlock::ReserveBlock (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", size, size, last_offset, needed_chunks, m_chunk_size); addr = m_addr + last_offset; break; } } last_offset = pos->first + pos->second * m_chunk_size; if (++pos == end) { // Last entry... const uint32_t chunks_left = CalculateChunksNeededForSize (m_byte_size - last_offset); if (chunks_left >= needed_chunks) { m_offset_to_chunk_size[last_offset] = needed_chunks; if (log) log->Printf ("[3] AllocatedBlock::ReserveBlock (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", size, size, last_offset, needed_chunks, m_chunk_size); addr = m_addr + last_offset; break; } } } } // const uint32_t total_chunks = m_allocated.size (); // uint32_t unallocated_idx = 0; // uint32_t allocated_idx = m_allocated.find_first(); // uint32_t first_chunk_idx = UINT32_MAX; // uint32_t num_chunks; // while (1) // { // if (allocated_idx == UINT32_MAX) // { // // No more bits are set starting from unallocated_idx, so we // // either have enough chunks for the request, or we don't. // // Eiter way we break out of the while loop... // num_chunks = total_chunks - unallocated_idx; // if (needed_chunks <= num_chunks) // first_chunk_idx = unallocated_idx; // break; // } // else if (allocated_idx > unallocated_idx) // { // // We have some allocated chunks, check if there are enough // // free chunks to satisfy the request? // num_chunks = allocated_idx - unallocated_idx; // if (needed_chunks <= num_chunks) // { // // Yep, we have enough! // first_chunk_idx = unallocated_idx; // break; // } // } // // while (unallocated_idx < total_chunks) // { // if (m_allocated[unallocated_idx]) // ++unallocated_idx; // else // break; // } // // if (unallocated_idx >= total_chunks) // break; // // allocated_idx = m_allocated.find_next(unallocated_idx); // } // // if (first_chunk_idx != UINT32_MAX) // { // const uint32_t end_bit_idx = unallocated_idx + needed_chunks; // for (uint32_t idx = first_chunk_idx; idx < end_bit_idx; ++idx) // m_allocated.set(idx); // return m_addr + m_chunk_size * first_chunk_idx; // } } LogSP log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); if (log) log->Printf ("AllocatedBlock::ReserveBlock (size = %u (0x%x)) => 0x%16.16llx", size, size, (uint64_t)addr); return addr; }
void Breakpoint::ModulesChanged (ModuleList &module_list, bool load) { if (load) { // The logic for handling new modules is: // 1) If the filter rejects this module, then skip it. // 2) Run through the current location list and if there are any locations // for that module, we mark the module as "seen" and we don't try to re-resolve // breakpoint locations for that module. // However, we do add breakpoint sites to these locations if needed. // 3) If we don't see this module in our breakpoint location list, call ResolveInModules. ModuleList new_modules; // We'll stuff the "unseen" modules in this list, and then resolve // them after the locations pass. Have to do it this way because // resolving breakpoints will add new locations potentially. const size_t num_locs = m_locations.GetSize(); for (size_t i = 0; i < module_list.GetSize(); i++) { bool seen = false; ModuleSP module_sp (module_list.GetModuleAtIndex (i)); if (!m_filter_sp->ModulePasses (module_sp)) continue; for (size_t loc_idx = 0; loc_idx < num_locs; loc_idx++) { BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx); if (!break_loc->IsEnabled()) continue; const Section *section = break_loc->GetAddress().GetSection(); if (section == NULL || section->GetModule() == module_sp.get()) { if (!seen) seen = true; if (!break_loc->ResolveBreakpointSite()) { LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); if (log) log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n", break_loc->GetID(), GetID()); } } } if (!seen) new_modules.AppendIfNeeded (module_sp); } if (new_modules.GetSize() > 0) { ResolveBreakpointInModules(new_modules); } } else { // Go through the currently set locations and if any have breakpoints in // the module list, then remove their breakpoint sites. // FIXME: Think about this... Maybe it's better to delete the locations? // Are we sure that on load-unload-reload the module pointer will remain // the same? Or do we need to do an equality on modules that is an // "equivalence"??? for (size_t i = 0; i < module_list.GetSize(); i++) { ModuleSP module_sp (module_list.GetModuleAtIndex (i)); if (m_filter_sp->ModulePasses (module_sp)) { const size_t num_locs = m_locations.GetSize(); for (size_t loc_idx = 0; loc_idx < num_locs; ++loc_idx) { BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx); const Section *section = break_loc->GetAddress().GetSection(); if (section && section->GetModule() == module_sp.get()) { // Remove this breakpoint since the shared library is // unloaded, but keep the breakpoint location around // so we always get complete hit count and breakpoint // lifetime info break_loc->ClearBreakpointSite(); } } } } } }
bool CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet) { // Put the packet data into the buffer in a thread safe fashion Mutex::Locker locker(m_bytes_mutex); LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); if (src && src_len > 0) { if (log && log->GetVerbose()) { PacketStreamType log_strm; DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS); log->Printf ("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__, (uint32_t)src_len, log_strm.GetData()); } m_bytes.append ((const char *)src, src_len); } // Make sure we at least have enough bytes for a packet header const size_t bytes_available = m_bytes.size(); if (bytes_available >= 8) { packet.SetData (&m_bytes[0], bytes_available, m_byte_order); uint32_t offset = 0; uint8_t reply_command = packet.GetU8(&offset); switch (reply_command) { case ePacketTypeRequest | KDP_EXCEPTION: case ePacketTypeRequest | KDP_TERMINATION: // We got an exception request, so be sure to send an ACK { PacketStreamType request_ack_packet (Stream::eBinary, m_addr_byte_size, m_byte_order); // Set the reply but and make the ACK packet request_ack_packet.PutHex8 (reply_command | ePacketTypeReply); request_ack_packet.PutHex8 (packet.GetU8(&offset)); request_ack_packet.PutHex16 (packet.GetU16(&offset)); request_ack_packet.PutHex32 (packet.GetU32(&offset)); m_is_running.SetValue(false, eBroadcastAlways); // Ack to the exception or termination SendRequestPacketNoLock (request_ack_packet); } // Fall through to case below to get packet contents case ePacketTypeReply | KDP_CONNECT: case ePacketTypeReply | KDP_DISCONNECT: case ePacketTypeReply | KDP_HOSTINFO: case ePacketTypeReply | KDP_VERSION: case ePacketTypeReply | KDP_MAXBYTES: case ePacketTypeReply | KDP_READMEM: case ePacketTypeReply | KDP_WRITEMEM: case ePacketTypeReply | KDP_READREGS: case ePacketTypeReply | KDP_WRITEREGS: case ePacketTypeReply | KDP_LOAD: case ePacketTypeReply | KDP_IMAGEPATH: case ePacketTypeReply | KDP_SUSPEND: case ePacketTypeReply | KDP_RESUMECPUS: case ePacketTypeReply | KDP_BREAKPOINT_SET: case ePacketTypeReply | KDP_BREAKPOINT_REMOVE: case ePacketTypeReply | KDP_REGIONS: case ePacketTypeReply | KDP_REATTACH: case ePacketTypeReply | KDP_HOSTREBOOT: case ePacketTypeReply | KDP_READMEM64: case ePacketTypeReply | KDP_WRITEMEM64: case ePacketTypeReply | KDP_BREAKPOINT_SET64: case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64: case ePacketTypeReply | KDP_KERNELVERSION: { offset = 2; const uint16_t length = packet.GetU16 (&offset); if (length <= bytes_available) { // We have an entire packet ready, we need to copy the data // bytes into a buffer that will be owned by the packet and // erase the bytes from our communcation buffer "m_bytes" packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length))); m_bytes.erase (0, length); if (log) { PacketStreamType log_strm; DumpPacket (log_strm, packet); log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } return true; } } break; default: // Unrecognized reply command byte, erase this byte and try to get back on track if (log) log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x", __FUNCTION__, (uint8_t)m_bytes[0]); m_bytes.erase(0, 1); break; } } packet.Clear(); return false; }