diff options
21 files changed, 554 insertions, 1060 deletions
diff --git a/lldb/include/lldb/Breakpoint/BreakpointSiteList.h b/lldb/include/lldb/Breakpoint/BreakpointSiteList.h index 76c1f52b058..0d4dafc4baa 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointSiteList.h +++ b/lldb/include/lldb/Breakpoint/BreakpointSiteList.h @@ -16,6 +16,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointSite.h" +#include "lldb/Host/Mutex.h" namespace lldb_private { @@ -130,31 +131,8 @@ public: bool BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id); - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint site with index \a i. - /// - /// @param[in] i - /// The breakpoint site index to seek for. - /// - /// @result - /// A shared pointer to the breakpoint site. May contain a NULL pointer if the - /// breakpoint doesn't exist. - //------------------------------------------------------------------ - lldb::BreakpointSiteSP - GetByIndex (uint32_t i); - - //------------------------------------------------------------------ - /// Returns a shared pointer to the breakpoint site with index \a i - const version. - /// - /// @param[in] i - /// The breakpoint site index to seek for. - /// - /// @result - /// A shared pointer to the breakpoint site. May contain a NULL pointer if the - /// breakpoint doesn't exist. - //------------------------------------------------------------------ - const lldb::BreakpointSiteSP - GetByIndex (uint32_t i) const; + void + ForEach (std::function <void(BreakpointSite *)> const &callback); //------------------------------------------------------------------ /// Removes the breakpoint site given by \b breakID from this list. @@ -179,9 +157,6 @@ public: //------------------------------------------------------------------ bool RemoveByAddress (lldb::addr_t addr); - - void - SetEnabledForAll(const bool enable, const lldb::break_id_t except_id = LLDB_INVALID_BREAK_ID); bool FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const; @@ -211,8 +186,18 @@ public: /// The number of elements. //------------------------------------------------------------------ size_t - GetSize() const { return m_bp_site_list.size(); } + GetSize() const + { + Mutex::Locker locker(m_mutex); + return m_bp_site_list.size(); + } + bool + IsEmpty() const + { + Mutex::Locker locker(m_mutex); + return m_bp_site_list.empty(); + } protected: typedef std::map<lldb::addr_t, lldb::BreakpointSiteSP> collection; @@ -222,13 +207,7 @@ protected: collection::const_iterator GetIDConstIterator(lldb::break_id_t breakID) const; - // This function exposes the m_bp_site_list. I use the in Process because there - // are places there where you want to iterate over the list, and it is less efficient - // to do it by index. FIXME: Find a better way to do this. - - const collection * - GetMap (); - + mutable Mutex m_mutex; collection m_bp_site_list; // The breakpoint site list. }; diff --git a/lldb/include/lldb/Symbol/SymbolContext.h b/lldb/include/lldb/Symbol/SymbolContext.h index 4ba9cd90f0e..5b12adebf5f 100644 --- a/lldb/include/lldb/Symbol/SymbolContext.h +++ b/lldb/include/lldb/Symbol/SymbolContext.h @@ -442,6 +442,11 @@ public: AppendIfUnique (const SymbolContext& sc, bool merge_symbol_into_function); + bool + MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc, + uint32_t start_idx = 0, + uint32_t stop_idx = UINT32_MAX); + uint32_t AppendIfUnique (const SymbolContextList& sc_list, bool merge_symbol_into_function); @@ -486,6 +491,30 @@ public: GetContextAtIndex(size_t idx, SymbolContext& sc) const; //------------------------------------------------------------------ + /// Direct reference accessor for a symbol context at index \a idx. + /// + /// The index \a idx must be a valid index, no error checking will + /// be done to ensure that it is valid. + /// + /// @param[in] idx + /// The zero based index into the symbol context list. + /// + /// @return + /// A const reference to the symbol context to fill in. + //------------------------------------------------------------------ + SymbolContext& + operator [] (size_t idx) + { + return m_symbol_contexts[idx]; + } + + const SymbolContext& + operator [] (size_t idx) const + { + return m_symbol_contexts[idx]; + } + + //------------------------------------------------------------------ /// Get accessor for the last symbol context in the list. /// /// @param[out] sc diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp index 4557abb37a7..27f85653d64 100644 --- a/lldb/source/Breakpoint/BreakpointResolverName.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -188,7 +188,7 @@ BreakpointResolverName::SearchCallback ) { SymbolContextList func_list; - SymbolContextList sym_list; + //SymbolContextList sym_list; uint32_t i; bool new_location; @@ -203,11 +203,10 @@ BreakpointResolverName::SearchCallback log->Warning ("Class/method function specification not supported yet.\n"); return Searcher::eCallbackReturnStop; } - - const bool include_symbols = false; + bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; + const bool include_symbols = filter_by_cu == false; const bool include_inlines = true; const bool append = true; - bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; switch (m_match_type) { @@ -228,26 +227,14 @@ BreakpointResolverName::SearchCallback if (start_func_idx < end_func_idx) lookup.Prune (func_list, start_func_idx); - // If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain - // symbols, since all the ones from a set compilation unit will have been found above already. - else if (!filter_by_cu) - { - const size_t start_symbol_idx = sym_list.GetSize(); - context.module_sp->FindFunctionSymbols (lookup.lookup_name, lookup.name_type_mask, sym_list); - const size_t end_symbol_idx = sym_list.GetSize(); - if (start_symbol_idx < end_symbol_idx) - lookup.Prune (func_list, start_symbol_idx); - } } } break; case Breakpoint::Regexp: if (context.module_sp) { - if (!filter_by_cu) - context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); - context.module_sp->FindFunctions (m_regex, - include_symbols, + context.module_sp->FindFunctions (m_regex, + !filter_by_cu, // include symbols only if we aren't filterning by CU include_inlines, append, func_list); @@ -283,33 +270,6 @@ BreakpointResolverName::SearchCallback { for (i = 0; i < func_list.GetSize(); i++) { - if (func_list.GetContextAtIndex(i, sc) == false) - continue; - - if (sc.function == NULL) - continue; - uint32_t j = 0; - while (j < sym_list.GetSize()) - { - SymbolContext symbol_sc; - if (sym_list.GetContextAtIndex(j, symbol_sc)) - { - if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) - { - if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress()) - { - sym_list.RemoveContextAtIndex(j); - continue; // Don't increment j - } - } - } - - j++; - } - } - - for (i = 0; i < func_list.GetSize(); i++) - { if (func_list.GetContextAtIndex(i, sc)) { if (sc.block && sc.block->GetInlinedFunctionInfo()) @@ -320,14 +280,21 @@ BreakpointResolverName::SearchCallback else if (sc.function) { break_addr = sc.function->GetAddressRange().GetBaseAddress(); - if (m_skip_prologue) + if (m_skip_prologue && break_addr.IsValid()) { - if (break_addr.IsValid()) - { - const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); - if (prologue_byte_size) - break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); - } + const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); + if (prologue_byte_size) + break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); + } + } + else if (sc.symbol) + { + break_addr = sc.symbol->GetAddress(); + if (m_skip_prologue && break_addr.IsValid()) + { + const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); + if (prologue_byte_size) + break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); } } @@ -351,35 +318,6 @@ BreakpointResolverName::SearchCallback } } - for (i = 0; i < sym_list.GetSize(); i++) - { - if (sym_list.GetContextAtIndex(i, sc)) - { - if (sc.symbol && sc.symbol->ValueIsAddress()) - { - break_addr = sc.symbol->GetAddress(); - - if (m_skip_prologue) - { - const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); - if (prologue_byte_size) - break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); - } - - if (filter.AddressPasses(break_addr)) - { - BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); - if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) - { - StreamString s; - bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); - if (log) - log->Printf ("Added location: %s\n", s.GetData()); - } - } - } - } - } return Searcher::eCallbackReturnContinue; } diff --git a/lldb/source/Breakpoint/BreakpointSiteList.cpp b/lldb/source/Breakpoint/BreakpointSiteList.cpp index 22f7d4502c0..68c4af18ec5 100644 --- a/lldb/source/Breakpoint/BreakpointSiteList.cpp +++ b/lldb/source/Breakpoint/BreakpointSiteList.cpp @@ -20,6 +20,7 @@ using namespace lldb; using namespace lldb_private; BreakpointSiteList::BreakpointSiteList() : + m_mutex (Mutex::eMutexTypeRecursive), m_bp_site_list() { } @@ -35,6 +36,7 @@ lldb::break_id_t BreakpointSiteList::Add(const BreakpointSiteSP &bp) { lldb::addr_t bp_site_load_addr = bp->GetLoadAddress(); + Mutex::Locker locker(m_mutex); collection::iterator iter = m_bp_site_list.find (bp_site_load_addr); if (iter == m_bp_site_list.end()) @@ -79,6 +81,7 @@ BreakpointSiteList::FindIDByAddress (lldb::addr_t addr) bool BreakpointSiteList::Remove (lldb::break_id_t break_id) { + Mutex::Locker locker(m_mutex); collection::iterator pos = GetIDIterator(break_id); // Predicate if (pos != m_bp_site_list.end()) { @@ -91,6 +94,7 @@ BreakpointSiteList::Remove (lldb::break_id_t break_id) bool BreakpointSiteList::RemoveByAddress (lldb::addr_t address) { + Mutex::Locker locker(m_mutex); collection::iterator pos = m_bp_site_list.find(address); if (pos != m_bp_site_list.end()) { @@ -120,6 +124,7 @@ private: BreakpointSiteList::collection::iterator BreakpointSiteList::GetIDIterator (lldb::break_id_t break_id) { + Mutex::Locker locker(m_mutex); return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range BreakpointSiteIDMatches(break_id)); // Predicate } @@ -127,6 +132,7 @@ BreakpointSiteList::GetIDIterator (lldb::break_id_t break_id) BreakpointSiteList::collection::const_iterator BreakpointSiteList::GetIDConstIterator (lldb::break_id_t break_id) const { + Mutex::Locker locker(m_mutex); return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range BreakpointSiteIDMatches(break_id)); // Predicate } @@ -134,6 +140,7 @@ BreakpointSiteList::GetIDConstIterator (lldb::break_id_t break_id) const BreakpointSiteSP BreakpointSiteList::FindByID (lldb::break_id_t break_id) { + Mutex::Locker locker(m_mutex); BreakpointSiteSP stop_sp; collection::iterator pos = GetIDIterator(break_id); if (pos != m_bp_site_list.end()) @@ -145,6 +152,7 @@ BreakpointSiteList::FindByID (lldb::break_id_t break_id) const BreakpointSiteSP BreakpointSiteList::FindByID (lldb::break_id_t break_id) const { + Mutex::Locker locker(m_mutex); BreakpointSiteSP stop_sp; collection::const_iterator pos = GetIDConstIterator(break_id); if (pos != m_bp_site_list.end()) @@ -157,7 +165,7 @@ BreakpointSiteSP BreakpointSiteList::FindByAddress (lldb::addr_t addr) { BreakpointSiteSP found_sp; - + Mutex::Locker locker(m_mutex); collection::iterator iter = m_bp_site_list.find(addr); if (iter != m_bp_site_list.end()) found_sp = iter->second; @@ -167,6 +175,7 @@ BreakpointSiteList::FindByAddress (lldb::addr_t addr) bool BreakpointSiteList::BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id) { + Mutex::Locker locker(m_mutex); collection::const_iterator pos = GetIDConstIterator(bp_site_id); if (pos != m_bp_site_list.end()) return pos->second->IsBreakpointAtThisSite (bp_id); @@ -188,44 +197,21 @@ BreakpointSiteList::Dump (Stream *s) const s->IndentLess(); } - -BreakpointSiteSP -BreakpointSiteList::GetByIndex (uint32_t i) -{ - BreakpointSiteSP stop_sp; - collection::iterator end = m_bp_site_list.end(); - collection::iterator pos; - uint32_t curr_i = 0; - for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) - { - if (curr_i == i) - stop_sp = pos->second; - } - return stop_sp; -} - -const BreakpointSiteSP -BreakpointSiteList::GetByIndex (uint32_t i) const +void +BreakpointSiteList::ForEach (std::function <void(BreakpointSite *)> const &callback) { - BreakpointSiteSP stop_sp; - collection::const_iterator end = m_bp_site_list.end(); - collection::const_iterator pos; - uint32_t curr_i = 0; - for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) - { - if (curr_i == i) - stop_sp = pos->second; - } - return stop_sp; + Mutex::Locker locker(m_mutex); + for (auto pair : m_bp_site_list) + callback (pair.second.get()); } bool BreakpointSiteList::FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const { - if (lower_bound > upper_bound) return false; + Mutex::Locker locker(m_mutex); collection::const_iterator lower, upper, pos; lower = m_bp_site_list.lower_bound(lower_bound); if (lower == m_bp_site_list.end() @@ -252,24 +238,3 @@ BreakpointSiteList::FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bo } return true; } - - -void -BreakpointSiteList::SetEnabledForAll (const bool enabled, const lldb::break_id_t except_id) -{ - collection::iterator end = m_bp_site_list.end(); - collection::iterator pos; - for (pos = m_bp_site_list.begin(); pos != end; ++pos) - { - if (except_id != LLDB_INVALID_BREAK_ID && except_id != pos->second->GetID()) - pos->second->SetEnabled (enabled); - else - pos->second->SetEnabled (!enabled); - } -} - -const BreakpointSiteList::collection * -BreakpointSiteList::GetMap () -{ - return &m_bp_site_list; -} diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index d8420ab8af1..205d2d9fb22 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -704,15 +704,50 @@ Module::FindFunctions (const RegularExpression& regex, const size_t num_matches = symbol_indexes.size(); if (num_matches) { - const bool merge_symbol_into_function = true; SymbolContext sc(this); - for (size_t i=0; i<num_matches; i++) + const size_t end_functions_added_index = sc_list.GetSize(); + size_t num_functions_added_to_sc_list = end_functions_added_index - start_size; + if (num_functions_added_to_sc_list == 0) { - sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); - SymbolType sym_type = sc.symbol->GetType(); - if (sc.symbol && (sym_type == eSymbolTypeCode || - sym_type == eSymbolTypeResolver)) - sc_list.AppendIfUnique (sc, merge_symbol_into_function); + // No functions were added, just symbols, so we can just append them + for (size_t i=0; i<num_matches; ++i) + { + sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); + SymbolType sym_type = sc.symbol->GetType(); + if (sc.symbol && (sym_type == eSymbolTypeCode || + sym_type == eSymbolTypeResolver)) + sc_list.Append(sc); + } + } + else + { + typedef std::map<lldb::addr_t, uint32_t> FileAddrToIndexMap; + FileAddrToIndexMap file_addr_to_index; + for (size_t i=start_size; i<end_functions_added_index; ++i) + { + const SymbolContext &sc = sc_list[i]; + if (sc.block) + continue; + file_addr_to_index[sc.function->GetAddressRange().GetBaseAddress().GetFileAddress()] = i; + } + + FileAddrToIndexMap::const_iterator end = file_addr_to_index.end(); + // Functions were added so we need to merge symbols into any + // existing function symbol contexts + for (size_t i=start_size; i<num_matches; ++i) + { + sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); + SymbolType sym_type = sc.symbol->GetType(); + if (sc.symbol && (sym_type == eSymbolTypeCode || + sym_type == eSymbolTypeResolver)) + { + FileAddrToIndexMap::const_iterator pos = file_addr_to_index.find(sc.symbol->GetAddress().GetFileAddress()); + if (pos == end) + sc_list.Append(sc); + else + sc_list[pos->second].symbol = sc.symbol; + } + } } } } diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp index b2beb912f43..ac91161f7d6 100644 --- a/lldb/source/Symbol/SymbolContext.cpp +++ b/lldb/source/Symbol/SymbolContext.cpp @@ -1023,6 +1023,10 @@ SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_in { for (pos = m_symbol_contexts.begin(); pos != end; ++pos) { + // Don't merge symbols into inlined function symbol contexts + if (pos->block && pos->block->GetContainingInlinedBlock()) + continue; + if (pos->function) { if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddress()) @@ -1044,6 +1048,49 @@ SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_in return true; } +bool +SymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc, + uint32_t start_idx, + uint32_t stop_idx) +{ + if (symbol_sc.symbol != NULL + && symbol_sc.comp_unit == NULL + && symbol_sc.function == NULL + && symbol_sc.block == NULL + && symbol_sc.line_entry.IsValid() == false) + { + if (symbol_sc.symbol->ValueIsAddress()) + { + const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx); + for (size_t i=start_idx; i<end; ++i) + { + const SymbolContext &function_sc = m_symbol_contexts[i]; + // Don't merge symbols into inlined function symbol contexts + if (function_sc.block && function_sc.block->GetContainingInlinedBlock()) + continue; + + if (function_sc.function) + { + if (function_sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress()) + { + // Do we already have a function with this symbol? + if (function_sc.symbol == symbol_sc.symbol) + return true; // Already have a symbol context with this symbol, return true + + if (function_sc.symbol == NULL) + { + // We successfully merged this symbol into an existing symbol context + m_symbol_contexts[i].symbol = symbol_sc.symbol; + return true; + } + } + } + } + } + } + return false; +} + void SymbolContextList::Clear() { diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 1127446be51..92107d60802 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -2007,12 +2007,10 @@ Process::GetBreakpointSiteList() const void Process::DisableAllBreakpointSites () { - m_breakpoint_site_list.SetEnabledForAll (false); - size_t num_sites = m_breakpoint_site_list.GetSize(); - for (size_t i = 0; i < num_sites; i++) - { - DisableBreakpointSite (m_breakpoint_site_list.GetByIndex(i).get()); - } + m_breakpoint_site_list.ForEach([this](BreakpointSite *bp_site) -> void { +// bp_site->SetEnabled(true); + DisableBreakpointSite(bp_site); + }); } Error @@ -2116,29 +2114,26 @@ size_t Process::RemoveBreakpointOpcodesFromBuffer (addr_t bp_addr, size_t size, uint8_t *buf) const { size_t bytes_removed = 0; - addr_t intersect_addr; - size_t intersect_size; - size_t opcode_offset; - size_t idx; - BreakpointSiteSP bp_sp; BreakpointSiteList bp_sites_in_range; if (m_breakpoint_site_list.FindInRange (bp_addr, bp_addr + size, bp_sites_in_range)) { - for (idx = 0; (bp_sp = bp_sites_in_range.GetByIndex(idx)); ++idx) - { - if (bp_sp->GetType() == BreakpointSite::eSoftware) + bp_sites_in_range.ForEach([bp_addr, size, buf, &bytes_removed](BreakpointSite *bp_site) -> void { + if (bp_site->GetType() == BreakpointSite::eSoftware) { - if (bp_sp->IntersectsRange(bp_addr, size, &intersect_addr, &intersect_size, &opcode_offset)) + addr_t intersect_addr; + size_t intersect_size; + size_t opcode_offset; + if (bp_site->IntersectsRange(bp_addr, size, &intersect_addr, &intersect_size, &opcode_offset)) { assert(bp_addr <= intersect_addr && intersect_addr < bp_addr + size); assert(bp_addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= bp_addr + size); - assert(opcode_offset + intersect_size <= bp_sp->GetByteSize()); + assert(opcode_offset + intersect_size <= bp_site->GetByteSize()); size_t buf_offset = intersect_addr - bp_addr; - ::memcpy(buf + buf_offset, bp_sp->GetSavedOpcodeBytes() + opcode_offset, intersect_size); + ::memcpy(buf + buf_offset, bp_site->GetSavedOpcodeBytes() + opcode_offset, intersect_size); } } - } + }); } return bytes_removed; } @@ -2596,64 +2591,73 @@ Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error) // (enabled software breakpoints) any software traps (breakpoints) that we // may have placed in our tasks memory. - BreakpointSiteList::collection::const_iterator iter = m_breakpoint_site_list.GetMap()->lower_bound (addr); - BreakpointSiteList::collection::const_iterator end = m_breakpoint_site_list.GetMap()->end(); - - if (iter == end || iter->second->GetLoadAddress() > addr + size) - return WriteMemoryPrivate (addr, buf, size, error); - - BreakpointSiteList::collection::const_iterator pos; - size_t bytes_written = 0; - addr_t intersect_addr = 0; - size_t intersect_size = 0; - size_t opcode_offset = 0; - const uint8_t *ubuf = (const uint8_t *)buf; - - for (pos = iter; pos != end; ++pos) + BreakpointSiteList bp_sites_in_range; + + if (m_breakpoint_site_list.FindInRange (addr, addr + size, bp_sites_in_range)) { - BreakpointSiteSP bp; - bp = pos->second; - - assert(bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset)); - assert(addr <= intersect_addr && intersect_addr < addr + size); - assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size); - assert(opcode_offset + intersect_size <= bp->GetByteSize()); - - // Check for bytes before this breakpoint - const addr_t curr_addr = addr + bytes_written; - if (intersect_addr > curr_addr) + // No breakpoint sites overlap + if (bp_sites_in_range.IsEmpty()) + return WriteMemoryPrivate (addr, buf, size, error); + else { - // There are some bytes before this breakpoint that we need to - // just write to memory - size_t curr_size = intersect_addr - curr_addr; - size_t curr_bytes_written = WriteMemoryPrivate (curr_addr, - ubuf + bytes_written, - curr_size, - error); - bytes_written += curr_bytes_written; - if (curr_bytes_written != curr_size) - { - // We weren't able to write all of the requested bytes, we - // are done looping and will return the number of bytes that - // we have written so far. - break; - } - } + const uint8_t *ubuf = (const uint8_t *)buf; + uint64_t bytes_written = 0; - // Now write any bytes that would cover up any software breakpoints - // directly into the breakpoint opcode buffer - ::memcpy(bp->GetSavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, intersect_size); - bytes_written += intersect_size; + bp_sites_in_range.ForEach([this, addr, size, &bytes_written, &ubuf, &error](BreakpointSite *bp) -> void { + + if (error.Success()) + { + addr_t intersect_addr; + size_t intersect_size; + size_t opcode_offset; + const bool intersects = bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset); + assert(intersects); + assert(addr <= intersect_addr && intersect_addr < addr + size); + assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size); + assert(opcode_offset + intersect_size <= bp->GetByteSize()); + + // Check for bytes before this breakpoint + const addr_t curr_addr = addr + bytes_written; + if (intersect_addr > curr_addr) + { + // There are some bytes before this breakpoint that we need to + // just write to memory + size_t curr_size = intersect_addr - curr_addr; + size_t curr_bytes_written = WriteMemoryPrivate (curr_addr, + ubuf + bytes_written, + curr_size, + error); + bytes_written += curr_bytes_written; + if (curr_bytes_written != curr_size) + { + // We weren't able to write all of the requested bytes, we + // are done looping and will return the number of bytes that + // we have written so far. + if (error.Success()) + error.SetErrorToGenericError(); + } + } + // Now write any bytes that would cover up any software breakpoints + // directly into the breakpoint opcode buffer + ::memcpy(bp->GetSavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, intersect_size); + bytes_written += intersect_size; + } + }); + + if (bytes_written < size) + bytes_written += WriteMemoryPrivate (addr + bytes_written, + ubuf + bytes_written, + size - bytes_written, + error); + } + } + else + { + return WriteMemoryPrivate (addr, buf, size, error); } // Write any remaining bytes after the last breakpoint if we have any left - if (bytes_written < size) - bytes_written += WriteMemoryPrivate (addr + bytes_written, - ubuf + bytes_written, - size - bytes_written, - error); - - return bytes_written; + return 0; //bytes_written; } size_t diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp index b91452a28c1..bcbcf983ff7 100644 --- a/lldb/tools/debugserver/source/DNB.cpp +++ b/lldb/tools/debugserver/source/DNB.cpp @@ -901,227 +901,44 @@ DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask) } // Breakpoints -nub_break_t +nub_bool_t DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware) { MachProcessSP procSP; if (GetProcessSP (pid, procSP)) - { - return procSP->CreateBreakpoint(addr, size, hardware, THREAD_NULL); - } - return INVALID_NUB_BREAK_ID; -} - -nub_bool_t -DNBBreakpointClear (nub_process_t pid, nub_break_t breakID) -{ - if (NUB_BREAK_ID_IS_VALID(breakID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->DisableBreakpoint(breakID, true); - } - } - return false; // Failed -} - -nub_ssize_t -DNBBreakpointGetHitCount (nub_process_t pid, nub_break_t breakID) -{ - if (NUB_BREAK_ID_IS_VALID(breakID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID); - if (bp) - return bp->GetHitCount(); - } - } - return 0; -} - -nub_ssize_t -DNBBreakpointGetIgnoreCount (nub_process_t pid, nub_break_t breakID) -{ - if (NUB_BREAK_ID_IS_VALID(breakID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID); - if (bp) - return bp->GetIgnoreCount(); - } - } - return 0; -} - -nub_bool_t -DNBBreakpointSetIgnoreCount (nub_process_t pid, nub_break_t breakID, nub_size_t ignore_count) -{ - if (NUB_BREAK_ID_IS_VALID(breakID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID); - if (bp) - { - bp->SetIgnoreCount(ignore_count); - return true; - } - } - } + return procSP->CreateBreakpoint(addr, size, hardware) != NULL; return false; } -// Set the callback function for a given breakpoint. The callback function will -// get called as soon as the breakpoint is hit. The function will be called -// with the process ID, thread ID, breakpoint ID and the baton, and can return -// nub_bool_t -DNBBreakpointSetCallback (nub_process_t pid, nub_break_t breakID, DNBCallbackBreakpointHit callback, void *baton) -{ - if (NUB_BREAK_ID_IS_VALID(breakID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - DNBBreakpoint *bp = procSP->Breakpoints().FindByID(breakID); - if (bp) - { - bp->SetCallback(callback, baton); - return true; - } - } - } - return false; -} - -//---------------------------------------------------------------------- -// Dump the breakpoints stats for process PID for a breakpoint by ID. -//---------------------------------------------------------------------- -void -DNBBreakpointPrint (nub_process_t pid, nub_break_t breakID) +DNBBreakpointClear (nub_process_t pid, nub_addr_t addr) { MachProcessSP procSP; if (GetProcessSP (pid, procSP)) - procSP->DumpBreakpoint(breakID); + return procSP->DisableBreakpoint(addr, true); + return false; // Failed } + //---------------------------------------------------------------------- // Watchpoints //---------------------------------------------------------------------- -nub_watch_t +nub_bool_t DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware) { MachProcessSP procSP; if (GetProcessSP (pid, procSP)) - { - return procSP->CreateWatchpoint(addr, size, watch_flags, hardware, THREAD_NULL); - } - return INVALID_NUB_WATCH_ID; -} - -nub_bool_t -DNBWatchpointClear (nub_process_t pid, nub_watch_t watchID) -{ - if (NUB_WATCH_ID_IS_VALID(watchID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->DisableWatchpoint(watchID, true); - } - } - return false; // Failed -} - -nub_ssize_t -DNBWatchpointGetHitCount (nub_process_t pid, nub_watch_t watchID) -{ - if (NUB_WATCH_ID_IS_VALID(watchID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID); - if (bp) - return bp->GetHitCount(); - } - } - return 0; -} - -nub_ssize_t -DNBWatchpointGetIgnoreCount (nub_process_t pid, nub_watch_t watchID) -{ - if (NUB_WATCH_ID_IS_VALID(watchID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID); - if (bp) - return bp->GetIgnoreCount(); - } - } - return 0; -} - -nub_bool_t -DNBWatchpointSetIgnoreCount (nub_process_t pid, nub_watch_t watchID, nub_size_t ignore_count) -{ - if (NUB_WATCH_ID_IS_VALID(watchID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID); - if (bp) - { - bp->SetIgnoreCount(ignore_count); - return true; - } - } - } + return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL; return false; } -// Set the callback function for a given watchpoint. The callback function will -// get called as soon as the watchpoint is hit. The function will be called -// with the process ID, thread ID, watchpoint ID and the baton, and can return -// nub_bool_t -DNBWatchpointSetCallback (nub_process_t pid, nub_watch_t watchID, DNBCallbackBreakpointHit callback, void *baton) -{ - if (NUB_WATCH_ID_IS_VALID(watchID)) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - DNBBreakpoint *bp = procSP->Watchpoints().FindByID(watchID); - if (bp) - { - bp->SetCallback(callback, baton); - return true; - } - } - } - return false; -} - -//---------------------------------------------------------------------- -// Dump the watchpoints stats for process PID for a watchpoint by ID. -//---------------------------------------------------------------------- -void -DNBWatchpointPrint (nub_process_t pid, nub_watch_t watchID) +DNBWatchpointClear (nub_process_t pid, nub_addr_t addr) { MachProcessSP procSP; if (GetProcessSP (pid, procSP)) - procSP->DumpWatchpoint(watchID); + return procSP->DisableWatchpoint(addr, true); + return false; // Failed } //---------------------------------------------------------------------- diff --git a/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h index 54a462015b9..986cab9becb 100644 --- a/lldb/tools/debugserver/source/DNB.h +++ b/lldb/tools/debugserver/source/DNB.h @@ -121,24 +121,14 @@ const char * DNBThreadGetInfo (nub_process_t pid, nub_thread_t //---------------------------------------------------------------------- // Breakpoint functions //---------------------------------------------------------------------- -nub_break_t DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware) DNB_EXPORT; -nub_bool_t DNBBreakpointClear (nub_process_t pid, nub_break_t breakID) DNB_EXPORT; -nub_ssize_t DNBBreakpointGetHitCount (nub_process_t pid, nub_break_t breakID) DNB_EXPORT; -nub_ssize_t DNBBreakpointGetIgnoreCount (nub_process_t pid, nub_break_t breakID) DNB_EXPORT; -nub_bool_t DNBBreakpointSetIgnoreCount (nub_process_t pid, nub_break_t breakID, nub_size_t ignore_count) DNB_EXPORT; -nub_bool_t DNBBreakpointSetCallback (nub_process_t pid, nub_break_t breakID, DNBCallbackBreakpointHit callback, void *baton) DNB_EXPORT; -void DNBBreakpointPrint (nub_process_t pid, nub_break_t breakID) DNB_EXPORT; +nub_bool_t DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware) DNB_EXPORT; +nub_bool_t DNBBreakpointClear (nub_process_t pid, nub_addr_t addr) DNB_EXPORT; //---------------------------------------------------------------------- // Watchpoint functions //---------------------------------------------------------------------- -nub_watch_t DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware) DNB_EXPORT; -nub_bool_t DNBWatchpointClear (nub_process_t pid, nub_watch_t watchID) DNB_EXPORT; -nub_ssize_t DNBWatchpointGetHitCount (nub_process_t pid, nub_watch_t watchID) DNB_EXPORT; -nub_ssize_t DNBWatchpointGetIgnoreCount (nub_process_t pid, nub_watch_t watchID) DNB_EXPORT; -nub_bool_t DNBWatchpointSetIgnoreCount (nub_process_t pid, nub_watch_t watchID, nub_size_t ignore_count) DNB_EXPORT; -nub_bool_t DNBWatchpointSetCallback (nub_process_t pid, nub_watch_t watchID, DNBCallbackBreakpointHit callback, void *baton) DNB_EXPORT; -void DNBWatchpointPrint (nub_process_t pid, nub_watch_t watchID) DNB_EXPORT; +nub_bool_t DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware) DNB_EXPORT; +nub_bool_t DNBWatchpointClear (nub_process_t pid, nub_addr_t addr) DNB_EXPORT; uint32_t DNBWatchpointGetNumSupportedHWP (nub_process_t pid) DNB_EXPORT; const DNBRegisterSetInfo * diff --git a/lldb/tools/debugserver/source/DNBBreakpoint.cpp b/lldb/tools/debugserver/source/DNBBreakpoint.cpp index 66706870305..246797c8dae 100644 --- a/lldb/tools/debugserver/source/DNBBreakpoint.cpp +++ b/lldb/tools/debugserver/source/DNBBreakpoint.cpp @@ -12,16 +12,17 @@ //===----------------------------------------------------------------------===// #include "DNBBreakpoint.h" +#include "MachProcess.h" +#include <assert.h> #include <algorithm> #include <inttypes.h> #include "DNBLog.h" #pragma mark -- DNBBreakpoint -DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, nub_thread_t tid, bool hardware) : - m_breakID(GetNextID()), - m_tid(tid), - m_byte_size(byte_size), +DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, bool hardware) : + m_retain_count (1), + m_byte_size (byte_size), m_opcode(), m_addr(addr), m_enabled(0), @@ -29,11 +30,7 @@ DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, nub_thread_t m_is_watchpoint(0), m_watch_read(0), m_watch_write(0), - m_hw_index(INVALID_NUB_HW_INDEX), - m_hit_count(0), - m_ignore_count(0), - m_callback(NULL), - m_callback_baton(NULL) + m_hw_index(INVALID_NUB_HW_INDEX) { } @@ -41,71 +38,27 @@ DNBBreakpoint::~DNBBreakpoint() { } -nub_break_t -DNBBreakpoint::GetNextID() -{ - static uint32_t g_nextBreakID = 0; - return ++g_nextBreakID; -} - -void -DNBBreakpoint::SetCallback(DNBCallbackBreakpointHit callback, void *callback_baton) -{ - m_callback = callback; - m_callback_baton = callback_baton; -} - - -// RETURNS - true if we should stop at this breakpoint, false if we -// should continue. - -bool -DNBBreakpoint::BreakpointHit(nub_process_t pid, nub_thread_t tid) -{ - m_hit_count++; - - if (m_hit_count > m_ignore_count) - { - if (m_callback) - return m_callback(pid, tid, GetID(), m_callback_baton); - return true; - } - return false; -} - void DNBBreakpoint::Dump() const { if (IsBreakpoint()) { - DNBLog ("DNBBreakpoint %u: tid = %8.8" PRIx64 " addr = 0x%llx state = %s type = %s breakpoint hw_index = %i hit_count = %-4u ignore_count = %-4u callback = %p baton = %p", - m_breakID, - m_tid, + DNBLog ("DNBBreakpoint addr = 0x%llx state = %s type = %s breakpoint hw_index = %i", (uint64_t)m_addr, m_enabled ? "enabled " : "disabled", IsHardware() ? "hardware" : "software", - GetHardwareIndex(), - GetHitCount(), - GetIgnoreCount(), - m_callback, - m_callback_baton); + GetHardwareIndex()); } else { - DNBLog ("DNBBreakpoint %u: tid = %8.8" PRIx64 " addr = 0x%llx size = %llu state = %s type = %s watchpoint (%s%s) hw_index = %i hit_count = %-4u ignore_count = %-4u callback = %p baton = %p", - m_breakID, - m_tid, + DNBLog ("DNBBreakpoint addr = 0x%llx size = %llu state = %s type = %s watchpoint (%s%s) hw_index = %i", (uint64_t)m_addr, (uint64_t)m_byte_size, m_enabled ? "enabled " : "disabled", IsHardware() ? "hardware" : "software", m_watch_read ? "r" : "", m_watch_write ? "w" : "", - GetHardwareIndex(), - GetHitCount(), - GetIgnoreCount(), - m_callback, - m_callback_baton); + GetHardwareIndex()); } } @@ -120,46 +73,18 @@ DNBBreakpointList::~DNBBreakpointList() } -nub_break_t -DNBBreakpointList::Add(const DNBBreakpoint& bp) -{ - m_breakpoints.push_back(bp); - return m_breakpoints.back().GetID(); -} - -bool -DNBBreakpointList::ShouldStop(nub_process_t pid, nub_thread_t tid, nub_break_t breakID) -{ - DNBBreakpoint *bp = FindByID (breakID); - if (bp) - { - // Let the breakpoint decide if it should stop here (could not have - // reached it's target hit count yet, or it could have a callback - // that decided it shouldn't stop (shared library loads/unloads). - return bp->BreakpointHit(pid, tid); - } - // We should stop here since this breakpoint isn't valid anymore or it - // doesn't exist. - return true; -} - -nub_break_t -DNBBreakpointList::FindIDByAddress (nub_addr_t addr) +DNBBreakpoint * +DNBBreakpointList::Add(nub_addr_t addr, nub_size_t length, bool hardware) { - DNBBreakpoint *bp = FindByAddress (addr); - if (bp) - { - DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBBreakpointList::%s ( addr = 0x%16.16llx ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID()); - return bp->GetID(); - } - DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBBreakpointList::%s ( addr = 0x%16.16llx ) => NONE", __FUNCTION__, (uint64_t)addr); - return INVALID_NUB_BREAK_ID; + m_breakpoints.insert(std::make_pair(addr, DNBBreakpoint(addr, length, hardware))); + iterator pos = m_breakpoints.find (addr); + return &pos->second; } bool -DNBBreakpointList::Remove (nub_break_t breakID) +DNBBreakpointList::Remove (nub_addr_t addr) { - iterator pos = GetBreakIDIterator(breakID); // Predicate + iterator pos = m_breakpoints.find(addr); if (pos != m_breakpoints.end()) { m_breakpoints.erase(pos); @@ -168,146 +93,133 @@ DNBBreakpointList::Remove (nub_break_t breakID) return false; } - -class BreakpointIDMatches -{ -public: - BreakpointIDMatches (nub_break_t breakID) : m_breakID(breakID) {} - bool operator() (const DNBBreakpoint& bp) const - { - return m_breakID == bp.GetID(); - } - private: - const nub_break_t m_breakID; -}; - -class BreakpointAddressMatches -{ -public: - BreakpointAddressMatches (nub_addr_t addr) : m_addr(addr) {} - bool operator() (const DNBBreakpoint& bp) const - { - return m_addr == bp.Address(); - } - private: - const nub_addr_t m_addr; -}; - -DNBBreakpointList::iterator -DNBBreakpointList::GetBreakIDIterator (nub_break_t breakID) -{ - return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range - BreakpointIDMatches(breakID)); // Predicate -} - -DNBBreakpointList::const_iterator -DNBBreakpointList::GetBreakIDConstIterator (nub_break_t breakID) const -{ - return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range - BreakpointIDMatches(breakID)); // Predicate -} - DNBBreakpoint * -DNBBreakpointList::FindByID (nub_break_t breakID) +DNBBreakpointList::FindByAddress (nub_addr_t addr) { - iterator pos = GetBreakIDIterator(breakID); + iterator pos = m_breakpoints.find(addr); if (pos != m_breakpoints.end()) - return &(*pos); + return &pos->second; return NULL; } const DNBBreakpoint * -DNBBreakpointList::FindByID (nub_break_t breakID) const +DNBBreakpointList::FindByAddress (nub_addr_t addr) const { - const_iterator pos = GetBreakIDConstIterator(breakID); + const_iterator pos = m_breakpoints.find(addr); if (pos != m_breakpoints.end()) - return &(*pos); - + return &pos->second; + return NULL; } -DNBBreakpoint * -DNBBreakpointList::FindByAddress (nub_addr_t addr) +// Finds the next breakpoint at an address greater than or equal to "addr" +size_t +DNBBreakpointList::FindBreakpointsThatOverlapRange (nub_addr_t addr, + nub_addr_t size, + std::vector<DNBBreakpoint *> &bps) { + bps.clear(); iterator end = m_breakpoints.end(); - iterator pos = std::find_if(m_breakpoints.begin(), end, // Search full range - BreakpointAddressMatches(addr)); // Predicate + // Find the first breakpoint with an address >= to "addr" + iterator pos = m_breakpoints.lower_bound(addr); if (pos != end) - return &(*pos); - - return NULL; -} - -const DNBBreakpoint * -DNBBreakpointList::FindByAddress (nub_addr_t addr) const -{ - const_iterator end = m_breakpoints.end(); - const_iterator pos = std::find_if(m_breakpoints.begin(), end, // Search full range - BreakpointAddressMatches(addr)); // Predicate - if (pos != end) - return &(*pos); - - return NULL; -} - -bool -DNBBreakpointList::SetCallback(nub_break_t breakID, DNBCallbackBreakpointHit callback, void *callback_baton) -{ - DNBBreakpoint *bp = FindByID (breakID); - if (bp) { - bp->SetCallback(callback, callback_baton); - return true; + if (pos != m_breakpoints.begin()) + { + // Watch out for a breakpoint at an address less than "addr" that might still overlap + iterator prev_pos = pos; + --prev_pos; + if (prev_pos->second.IntersectsRange (addr, size, NULL, NULL, NULL)) + bps.push_back (&pos->second); + + } + + while (pos != end) + { + // When we hit a breakpoint whose start address is greater than "addr + size" we are done. + // Do the math in a way that doesn't risk unsigned overflow with bad input. + if ((pos->second.Address() - addr) >= size) + break; + + // Check if this breakpoint overlaps, and if it does, add it to the list + if (pos->second.IntersectsRange (addr, size, NULL, NULL, NULL)) + { + bps.push_back (&pos->second); + ++pos; + } + } } - return false; + return bps.size(); } - void DNBBreakpointList::Dump() const { const_iterator pos; const_iterator end = m_breakpoints.end(); for (pos = m_breakpoints.begin(); pos != end; ++pos) - (*pos).Dump(); + pos->second.Dump(); +} + +void +DNBBreakpointList::DisableAll () +{ + iterator pos, end = m_breakpoints.end(); + for (pos = m_breakpoints.begin(); pos != end; ++pos) + pos->second.SetEnabled(false); } -DNBBreakpoint * -DNBBreakpointList::GetByIndex (uint32_t i) +void +DNBBreakpointList::RemoveTrapsFromBuffer (nub_addr_t addr, nub_size_t size, void *p) const { - iterator end = m_breakpoints.end(); - iterator pos; - uint32_t curr_i = 0; - for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) + uint8_t *buf = (uint8_t *)p; + const_iterator end = m_breakpoints.end(); + const_iterator pos = m_breakpoints.lower_bound(addr); + while (pos != end && (pos->first < (addr + size))) { - if (curr_i == i) - return &(*pos); + nub_addr_t intersect_addr; + nub_size_t intersect_size; + nub_size_t opcode_offset; + const DNBBreakpoint &bp = pos->second; + if (bp.IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset)) + { + assert(addr <= intersect_addr && intersect_addr < addr + size); + assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size); + assert(opcode_offset + intersect_size <= bp.ByteSize()); + nub_size_t buf_offset = intersect_addr - addr; + ::memcpy(buf + buf_offset, bp.SavedOpcodeBytes() + opcode_offset, intersect_size); + } + ++pos; } - return NULL; } void -DNBBreakpointList::DisableAll () +DNBBreakpointList::DisableAllBreakpoints(MachProcess *process) { iterator pos, end = m_breakpoints.end(); for (pos = m_breakpoints.begin(); pos != end; ++pos) - (*pos).SetEnabled(false); + process->DisableBreakpoint(pos->second.Address(), false); } +void +DNBBreakpointList::DisableAllWatchpoints(MachProcess *process) +{ + iterator pos, end = m_breakpoints.end(); + for (pos = m_breakpoints.begin(); pos != end; ++pos) + process->DisableWatchpoint(pos->second.Address(), false); +} -const DNBBreakpoint * -DNBBreakpointList::GetByIndex (uint32_t i) const +void +DNBBreakpointList::RemoveDisabled() { - const_iterator end = m_breakpoints.end(); - const_iterator pos; - uint32_t curr_i = 0; - for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) + iterator pos = m_breakpoints.begin(); + while (pos != m_breakpoints.end()) { - if (curr_i == i) - return &(*pos); + if (!pos->second.IsEnabled()) + pos = m_breakpoints.erase(pos); + else + ++pos; } - return NULL; } - diff --git a/lldb/tools/debugserver/source/DNBBreakpoint.h b/lldb/tools/debugserver/source/DNBBreakpoint.h index e6a340614bb..c764dbd6cf2 100644 --- a/lldb/tools/debugserver/source/DNBBreakpoint.h +++ b/lldb/tools/debugserver/source/DNBBreakpoint.h @@ -14,25 +14,33 @@ #ifndef __DNBBreakpoint_h__ #define __DNBBreakpoint_h__ -#include <list> +#include <mach/mach.h> + +#include <map> +#include <vector> #include "DNBDefs.h" +class MachProcess; + class DNBBreakpoint { public: - DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, nub_thread_t tid, bool hardware); + DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, bool hardware); ~DNBBreakpoint(); - nub_break_t GetID() const { return m_breakID; } nub_size_t ByteSize() const { return m_byte_size; } uint8_t * SavedOpcodeBytes() { return &m_opcode[0]; } const uint8_t * SavedOpcodeBytes() const { return &m_opcode[0]; } nub_addr_t Address() const { return m_addr; } - nub_thread_t ThreadID() const { return m_tid; } +// nub_thread_t ThreadID() const { return m_tid; } bool IsEnabled() const { return m_enabled; } - bool IntersectsRange(nub_addr_t addr, nub_size_t size, nub_addr_t *intersect_addr, nub_size_t *intersect_size, nub_size_t *opcode_offset) const + bool IntersectsRange(nub_addr_t addr, + nub_size_t size, + nub_addr_t *intersect_addr, + nub_size_t *intersect_size, + nub_size_t *opcode_offset) const { // We only use software traps for software breakpoints if (IsBreakpoint() && IsEnabled() && !IsHardware()) @@ -93,19 +101,21 @@ public: bool IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; } uint32_t GetHardwareIndex() const { return m_hw_index; } void SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; } -// StateType GetState() const { return m_state; } -// void SetState(StateType newState) { m_state = newState; } - int32_t GetHitCount() const { return m_hit_count; } - int32_t GetIgnoreCount() const { return m_ignore_count; } - void SetIgnoreCount(int32_t n) { m_ignore_count = n; } - bool BreakpointHit(nub_process_t pid, nub_thread_t tid); - void SetCallback(DNBCallbackBreakpointHit callback, void *callback_baton); void Dump() const; + uint32_t Retain () + { + return ++m_retain_count; + } + uint32_t Release () + { + if (m_retain_count == 0) + return 0; + return --m_retain_count; + } private: - nub_break_t m_breakID; // The unique identifier for this breakpoint - nub_thread_t m_tid; // Thread ID for the breakpoint (can be INVALID_NUB_THREAD for all threads) - nub_size_t m_byte_size; // Length in bytes of the breakpoint if set in memory + uint32_t m_retain_count; // Each breakpoint is maintained by address and is ref counted in case multiple people set a breakpoint at the same address + uint32_t m_byte_size; // Length in bytes of the breakpoint if set in memory uint8_t m_opcode[8]; // Saved opcode bytes nub_addr_t m_addr; // Address of this breakpoint uint32_t m_enabled:1, // Flags for this breakpoint @@ -114,14 +124,6 @@ private: m_watch_read:1, // 1 if we stop when the watched data is read from m_watch_write:1; // 1 if we stop when the watched data is written to uint32_t m_hw_index; // The hardware resource index for this breakpoint/watchpoint - int32_t m_hit_count; // Number of times this breakpoint has been hit - int32_t m_ignore_count; // Number of times to ignore this breakpoint - DNBCallbackBreakpointHit - m_callback; // Callback to call when this breakpoint gets hit - void * m_callback_baton; // Callback user data to pass to callback - - static nub_break_t GetNextID(); - }; @@ -131,28 +133,31 @@ public: DNBBreakpointList(); ~DNBBreakpointList(); - nub_break_t Add (const DNBBreakpoint& bp); - nub_break_t FindIDByAddress (nub_addr_t addr); - bool ShouldStop (nub_process_t pid, nub_thread_t tid, nub_break_t breakID); - bool Remove (nub_break_t breakID); - bool SetCallback (nub_break_t breakID, DNBCallbackBreakpointHit callback, void *callback_baton); + DNBBreakpoint * Add (nub_addr_t addr, nub_size_t length, bool hardware); + bool Remove (nub_addr_t addr); DNBBreakpoint * FindByAddress (nub_addr_t addr); const DNBBreakpoint * FindByAddress (nub_addr_t addr) const; - DNBBreakpoint * FindByID (nub_break_t breakID); - const DNBBreakpoint * FindByID (nub_break_t breakID) const; + + size_t FindBreakpointsThatOverlapRange (nub_addr_t addr, + nub_addr_t size, + std::vector<DNBBreakpoint *> &bps); + void Dump () const; size_t Size() const { return m_breakpoints.size(); } - DNBBreakpoint * GetByIndex (uint32_t i); - const DNBBreakpoint * GetByIndex (uint32_t i) const; void DisableAll (); + void RemoveTrapsFromBuffer (nub_addr_t addr, + nub_size_t size, + void *buf) const; + + void DisableAllBreakpoints (MachProcess *process); + void DisableAllWatchpoints(MachProcess *process); + void RemoveDisabled (); protected: - typedef std::list<DNBBreakpoint> collection; + typedef std::map<nub_addr_t, DNBBreakpoint> collection; typedef collection::iterator iterator; typedef collection::const_iterator const_iterator; - iterator GetBreakIDIterator(nub_break_t breakID); - const_iterator GetBreakIDConstIterator(nub_break_t breakID) const; collection m_breakpoints; }; diff --git a/lldb/tools/debugserver/source/DNBDefs.h b/lldb/tools/debugserver/source/DNBDefs.h index e4c95a90d49..78364e782dd 100644 --- a/lldb/tools/debugserver/source/DNBDefs.h +++ b/lldb/tools/debugserver/source/DNBDefs.h @@ -55,15 +55,12 @@ typedef uint64_t nub_addr_t; typedef size_t nub_size_t; typedef ssize_t nub_ssize_t; -typedef uint32_t nub_break_t; -typedef uint32_t nub_watch_t; typedef uint32_t nub_index_t; typedef pid_t nub_process_t; typedef uint64_t nub_thread_t; typedef uint32_t nub_event_t; typedef uint32_t nub_bool_t; -#define INVALID_NUB_BREAK_ID ((nub_break_t)0) #define INVALID_NUB_PROCESS ((nub_process_t)0) #define INVALID_NUB_THREAD ((nub_thread_t)0) #define INVALID_NUB_WATCH_ID ((nub_watch_t)0) @@ -71,9 +68,6 @@ typedef uint32_t nub_bool_t; #define INVALID_NUB_REGNUM UINT32_MAX #define NUB_GENERIC_ERROR UINT32_MAX -#define NUB_BREAK_ID_IS_VALID(breakID) ((breakID) != (INVALID_NUB_BREAK_ID)) -#define NUB_WATCH_ID_IS_VALID(watchID) ((watchID) != (INVALID_NUB_WATCH_ID)) - // Watchpoint types #define WATCH_TYPE_READ (1u << 0) #define WATCH_TYPE_WRITE (1u << 1) @@ -361,7 +355,6 @@ enum DNBProfileDataScanType eProfileAll = 0xffffffff }; -typedef nub_bool_t (*DNBCallbackBreakpointHit)(nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton); typedef nub_addr_t (*DNBCallbackNameToAddress)(nub_process_t pid, const char *name, const char *shlib_regex, void *baton); typedef nub_size_t (*DNBCallbackCopyExecutableImageInfos)(nub_process_t pid, struct DNBExecutableImageInfo **image_infos, nub_bool_t only_changed, void *baton); typedef void (*DNBCallbackLog)(void *baton, uint32_t flags, const char *format, va_list args); diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp index 7397fe94aca..2eab3784e19 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp @@ -557,29 +557,6 @@ MachProcess::Detach() return true; } -nub_size_t -MachProcess::RemoveTrapsFromBuffer (nub_addr_t addr, nub_size_t size, uint8_t *buf) const -{ - nub_size_t bytes_removed = 0; - const DNBBreakpoint *bp; - nub_addr_t intersect_addr; - nub_size_t intersect_size; - nub_size_t opcode_offset; - nub_size_t idx; - for (idx = 0; (bp = m_breakpoints.GetByIndex(idx)) != NULL; ++idx) - { - if (bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset)) - { - assert(addr <= intersect_addr && intersect_addr < addr + size); - assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size); - assert(opcode_offset + intersect_size <= bp->ByteSize()); - nub_size_t buf_offset = intersect_addr - addr; - ::memcpy(buf + buf_offset, bp->SavedOpcodeBytes() + opcode_offset, intersect_size); - } - } - return bytes_removed; -} - //---------------------------------------------------------------------- // ReadMemory from the MachProcess level will always remove any software // breakpoints from the memory buffer before returning. If you wish to @@ -599,7 +576,7 @@ MachProcess::ReadMemory (nub_addr_t addr, nub_size_t size, void *buf) // Then place any opcodes that fall into this range back into the buffer // before we return this to callers. if (bytes_read > 0) - RemoveTrapsFromBuffer (addr, size, (uint8_t *)buf); + m_breakpoints.RemoveTrapsFromBuffer (addr, bytes_read, buf); return bytes_read; } @@ -619,38 +596,28 @@ MachProcess::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf) // (enabled software breakpoints) any software traps (breakpoints) that we // may have placed in our tasks memory. - std::map<nub_addr_t, DNBBreakpoint *> addr_to_bp_map; - DNBBreakpoint *bp; - nub_size_t idx; - for (idx = 0; (bp = m_breakpoints.GetByIndex(idx)) != NULL; ++idx) - { - if (bp->IntersectsRange(addr, size, NULL, NULL, NULL)) - addr_to_bp_map[bp->Address()] = bp; - } - - // If we don't have any software breakpoints that are in this buffer, then - // we can just write memory and be done with it. - if (addr_to_bp_map.empty()) + std::vector<DNBBreakpoint *> bps; + + const size_t num_bps = m_breakpoints.FindBreakpointsThatOverlapRange(addr, size, bps); + if (num_bps == 0) return m_task.WriteMemory(addr, size, buf); - // If we make it here, we have some breakpoints that overlap and we need - // to work around them. - nub_size_t bytes_written = 0; nub_addr_t intersect_addr; nub_size_t intersect_size; nub_size_t opcode_offset; const uint8_t *ubuf = (const uint8_t *)buf; - std::map<nub_addr_t, DNBBreakpoint *>::iterator pos, end = addr_to_bp_map.end(); - for (pos = addr_to_bp_map.begin(); pos != end; ++pos) + + for (size_t i=0; i<num_bps; ++i) { - bp = pos->second; + DNBBreakpoint *bp = bps[i]; - assert(bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset)); + const bool intersects = bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset); + assert(intersects); assert(addr <= intersect_addr && intersect_addr < addr + size); assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size); assert(opcode_offset + intersect_size <= bp->ByteSize()); - + // Check for bytes before this breakpoint const nub_addr_t curr_addr = addr + bytes_written; if (intersect_addr > curr_addr) @@ -668,17 +635,17 @@ MachProcess::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf) break; } } - + // Now write any bytes that would cover up any software breakpoints // directly into the breakpoint opcode buffer ::memcpy(bp->SavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, intersect_size); bytes_written += intersect_size; } - + // Write any remaining bytes after the last breakpoint if we have any left if (bytes_written < size) bytes_written += m_task.WriteMemory(addr + bytes_written, size - bytes_written, ubuf + bytes_written); - + return bytes_written; } @@ -743,110 +710,105 @@ MachProcess::PrivateResume () m_task.Resume(); } -nub_break_t -MachProcess::CreateBreakpoint(nub_addr_t addr, nub_size_t length, bool hardware, thread_t tid) +DNBBreakpoint * +MachProcess::CreateBreakpoint(nub_addr_t addr, nub_size_t length, bool hardware) { - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = 0x%8.8llx, length = %llu, hardware = %i, tid = 0x%4.4x )", (uint64_t)addr, (uint64_t)length, hardware, tid); - if (hardware && tid == INVALID_NUB_THREAD) - tid = GetCurrentThread(); + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = 0x%8.8llx, length = %llu, hardware = %i)", (uint64_t)addr, (uint64_t)length, hardware); - DNBBreakpoint bp(addr, length, tid, hardware); - nub_break_t breakID = m_breakpoints.Add(bp); - if (EnableBreakpoint(breakID)) + DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); + if (bp) + bp->Retain(); + else + bp = m_breakpoints.Add(addr, length, hardware); + + if (EnableBreakpoint(addr)) { - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = 0x%8.8llx, length = %llu, tid = 0x%4.4x ) => %u", (uint64_t)addr, (uint64_t)length, tid, breakID); - return breakID; + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = 0x%8.8llx, length = %llu) => %p", (uint64_t)addr, (uint64_t)length, bp); + return bp; } - else + else if (bp->Release() == 0) { - m_breakpoints.Remove(breakID); + m_breakpoints.Remove(addr); } // We failed to enable the breakpoint - return INVALID_NUB_BREAK_ID; + return NULL; } -nub_watch_t -MachProcess::CreateWatchpoint(nub_addr_t addr, nub_size_t length, uint32_t watch_flags, bool hardware, thread_t tid) +DNBBreakpoint * +MachProcess::CreateWatchpoint(nub_addr_t addr, nub_size_t length, uint32_t watch_flags, bool hardware) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu, flags = 0x%8.8x, hardware = %i, tid = 0x%4.4x )", (uint64_t)addr, (uint64_t)length, watch_flags, hardware, tid); - if (hardware && tid == INVALID_NUB_THREAD) - tid = GetCurrentThread(); + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu, flags = 0x%8.8x, hardware = %i)", (uint64_t)addr, (uint64_t)length, watch_flags, hardware); - DNBBreakpoint watch(addr, length, tid, hardware); - watch.SetIsWatchpoint(watch_flags); + DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); + // since the Z packets only send an address, we can only have one watchpoint at + // an address. If there is already one, we must refuse to create another watchpoint + if (wp) + return NULL; + + wp = m_watchpoints.Add(addr, length, hardware); + wp->SetIsWatchpoint(watch_flags); - nub_watch_t watchID = m_watchpoints.Add(watch); - if (EnableWatchpoint(watchID)) + if (EnableWatchpoint(addr)) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu, tid = 0x%x) => %u", (uint64_t)addr, (uint64_t)length, tid, watchID); - return watchID; + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu) => %p", (uint64_t)addr, (uint64_t)length, wp); + return wp; } else { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu, tid = 0x%x) => FAILED (%u)", (uint64_t)addr, (uint64_t)length, tid, watchID); - m_watchpoints.Remove(watchID); + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu) => FAILED", (uint64_t)addr, (uint64_t)length); + m_watchpoints.Remove(addr); } // We failed to enable the watchpoint - return INVALID_NUB_BREAK_ID; + return NULL; } -nub_size_t -MachProcess::DisableAllBreakpoints(bool remove) +void +MachProcess::DisableAllBreakpoints (bool remove) { DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::%s (remove = %d )", __FUNCTION__, remove); - DNBBreakpoint *bp; - nub_size_t disabled_count = 0; - nub_size_t idx = 0; - while ((bp = m_breakpoints.GetByIndex(idx)) != NULL) - { - bool success = DisableBreakpoint(bp->GetID(), remove); - - if (success) - disabled_count++; - // If we failed to disable the breakpoint or we aren't removing the breakpoint - // increment the breakpoint index. Otherwise DisableBreakpoint will have removed - // the breakpoint at this index and we don't need to change it. - if ((success == false) || (remove == false)) - idx++; - } - return disabled_count; + + m_breakpoints.DisableAllBreakpoints (this); + + if (remove) + m_breakpoints.RemoveDisabled(); } -nub_size_t +void MachProcess::DisableAllWatchpoints(bool remove) { DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s (remove = %d )", __FUNCTION__, remove); - DNBBreakpoint *wp; - nub_size_t disabled_count = 0; - nub_size_t idx = 0; - while ((wp = m_watchpoints.GetByIndex(idx)) != NULL) - { - bool success = DisableWatchpoint(wp->GetID(), remove); - - if (success) - disabled_count++; - // If we failed to disable the watchpoint or we aren't removing the watchpoint - // increment the watchpoint index. Otherwise DisableWatchpoint will have removed - // the watchpoint at this index and we don't need to change it. - if ((success == false) || (remove == false)) - idx++; - } - return disabled_count; + + m_watchpoints.DisableAllWatchpoints(this); + + if (remove) + m_watchpoints.RemoveDisabled(); } bool -MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove) +MachProcess::DisableBreakpoint(nub_addr_t addr, bool remove) { - DNBBreakpoint *bp = m_breakpoints.FindByID (breakID); + DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); if (bp) { // After "exec" we might end up with a bunch of breakpoints that were disabled // manually, just ignore them if (!bp->IsEnabled()) + { + // Breakpoint might have been disabled by an exec + if (remove && bp->Release() == 0) + { + m_thread_list.NotifyBreakpointChanged(bp); + m_breakpoints.Remove(addr); + } return true; + } - nub_addr_t addr = bp->Address(); - DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, "MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx", breakID, remove, (uint64_t)addr); + // We have multiple references to this breakpoint, decrement the ref count + // and if it isn't zero, then return true; + if (remove && bp->Release() > 0) + return true; + + DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d )", (uint64_t)addr, remove); if (bp->IsHardware()) { @@ -859,9 +821,9 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove) if (remove) { m_thread_list.NotifyBreakpointChanged(bp); - m_breakpoints.Remove(breakID); + m_breakpoints.Remove(addr); } - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx (hardware) => success", breakID, remove, (uint64_t)addr); + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) (hardware) => success", (uint64_t)addr, remove); return true; } @@ -895,19 +857,19 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove) } else { - DNBLogError("MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx memory write failed when restoring original opcode", breakID, remove, (uint64_t)addr); + DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) memory write failed when restoring original opcode", addr, remove); } } else { - DNBLogWarning("MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx expected a breakpoint opcode but didn't find one.", breakID, remove, (uint64_t)addr); + DNBLogWarning("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) expected a breakpoint opcode but didn't find one.", addr, remove); // Set verify to true and so we can check if the original opcode has already been restored verify = true; } } else { - DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, "MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx is not enabled", breakID, remove, (uint64_t)addr); + DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) is not enabled", addr, remove); // Set verify to true and so we can check if the original opcode is there verify = true; } @@ -924,20 +886,20 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove) // SUCCESS bp->SetEnabled(false); // Let the thread list know that a breakpoint has been modified - if (remove) + if (remove && bp->Release() == 0) { m_thread_list.NotifyBreakpointChanged(bp); - m_breakpoints.Remove(breakID); + m_breakpoints.Remove(addr); } - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx => success", breakID, remove, (uint64_t)addr); + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) => success", (uint64_t)addr, remove); return true; } else { if (break_op_found) - DNBLogError("MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx: failed to restore original opcode", breakID, remove, (uint64_t)addr); + DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) : failed to restore original opcode", (uint64_t)addr, remove); else - DNBLogError("MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx: opcode changed", breakID, remove, (uint64_t)addr); + DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) : opcode changed", (uint64_t)addr, remove); } } else @@ -954,20 +916,24 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove) } else { - DNBLogError("MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) invalid breakpoint ID", breakID, remove); + DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) invalid breakpoint address", (uint64_t)addr, remove); } return false; } bool -MachProcess::DisableWatchpoint(nub_watch_t watchID, bool remove) +MachProcess::DisableWatchpoint(nub_addr_t addr, bool remove) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s(watchID = %d, remove = %d)", __FUNCTION__, watchID, remove); - DNBBreakpoint *wp = m_watchpoints.FindByID (watchID); + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s(addr = 0x%8.8llx, remove = %d)", __FUNCTION__, (uint64_t)addr, remove); + DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); if (wp) { + // If we have multiple references to a watchpoint, removing the watchpoint shouldn't clear it + if (remove && wp->Release() > 0) + return true; + nub_addr_t addr = wp->Address(); - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::DisableWatchpoint ( watchID = %d, remove = %d ) addr = 0x%8.8llx", watchID, remove, (uint64_t)addr); + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = %d )", (uint64_t)addr, remove); if (wp->IsHardware()) { @@ -977,8 +943,8 @@ MachProcess::DisableWatchpoint(nub_watch_t watchID, bool remove) { wp->SetEnabled(false); if (remove) - m_watchpoints.Remove(watchID); - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::Disablewatchpoint ( watchID = %d, remove = %d ) addr = 0x%8.8llx (hardware) => success", watchID, remove, (uint64_t)addr); + m_watchpoints.Remove(addr); + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::Disablewatchpoint ( addr = 0x%8.8llx, remove = %d ) (hardware) => success", (uint64_t)addr, remove); return true; } } @@ -987,50 +953,12 @@ MachProcess::DisableWatchpoint(nub_watch_t watchID, bool remove) } else { - DNBLogError("MachProcess::DisableWatchpoint ( watchID = %d, remove = %d ) invalid watchpoint ID", watchID, remove); + DNBLogError("MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = %d ) invalid watchpoint ID", (uint64_t)addr, remove); } return false; } -void -MachProcess::DumpBreakpoint(nub_break_t breakID) const -{ - DNBLogThreaded("MachProcess::DumpBreakpoint(breakID = %d)", breakID); - - if (NUB_BREAK_ID_IS_VALID(breakID)) - { - const DNBBreakpoint *bp = m_breakpoints.FindByID(breakID); - if (bp) - bp->Dump(); - else - DNBLog("MachProcess::DumpBreakpoint(breakID = %d): invalid breakID", breakID); - } - else - { - m_breakpoints.Dump(); - } -} - -void -MachProcess::DumpWatchpoint(nub_watch_t watchID) const -{ - DNBLogThreaded("MachProcess::DumpWatchpoint(watchID = %d)", watchID); - - if (NUB_BREAK_ID_IS_VALID(watchID)) - { - const DNBBreakpoint *wp = m_watchpoints.FindByID(watchID); - if (wp) - wp->Dump(); - else - DNBLog("MachProcess::DumpWatchpoint(watchID = %d): invalid watchID", watchID); - } - else - { - m_watchpoints.Dump(); - } -} - uint32_t MachProcess::GetNumSupportedHardwareWatchpoints () const { @@ -1038,16 +966,15 @@ MachProcess::GetNumSupportedHardwareWatchpoints () const } bool -MachProcess::EnableBreakpoint(nub_break_t breakID) +MachProcess::EnableBreakpoint(nub_addr_t addr) { - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::EnableBreakpoint ( breakID = %d )", breakID); - DNBBreakpoint *bp = m_breakpoints.FindByID (breakID); + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::EnableBreakpoint ( addr = 0x%8.8llx )", (uint64_t)addr); + DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); if (bp) { - nub_addr_t addr = bp->Address(); if (bp->IsEnabled()) { - DNBLogWarning("MachProcess::EnableBreakpoint ( breakID = %d ) addr = 0x%8.8llx: breakpoint already enabled.", breakID, (uint64_t)addr); + DNBLogWarning("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): breakpoint already enabled.", (uint64_t)addr); return true; } else @@ -1081,32 +1008,32 @@ MachProcess::EnableBreakpoint(nub_break_t breakID) bp->SetEnabled(true); // Let the thread list know that a breakpoint has been modified m_thread_list.NotifyBreakpointChanged(bp); - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::EnableBreakpoint ( breakID = %d ) addr = 0x%8.8llx: SUCCESS.", breakID, (uint64_t)addr); + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ) : SUCCESS.", (uint64_t)addr); return true; } else { - DNBLogError("MachProcess::EnableBreakpoint ( breakID = %d ) addr = 0x%8.8llx: breakpoint opcode verification failed.", breakID, (uint64_t)addr); + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): breakpoint opcode verification failed.", (uint64_t)addr); } } else { - DNBLogError("MachProcess::EnableBreakpoint ( breakID = %d ) addr = 0x%8.8llx: unable to read memory to verify breakpoint opcode.", breakID, (uint64_t)addr); + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): unable to read memory to verify breakpoint opcode.", (uint64_t)addr); } } else { - DNBLogError("MachProcess::EnableBreakpoint ( breakID = %d ) addr = 0x%8.8llx: unable to write breakpoint opcode to memory.", breakID, (uint64_t)addr); + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): unable to write breakpoint opcode to memory.", (uint64_t)addr); } } else { - DNBLogError("MachProcess::EnableBreakpoint ( breakID = %d ) addr = 0x%8.8llx: unable to read memory at breakpoint address.", breakID, (uint64_t)addr); + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): unable to read memory at breakpoint address.", (uint64_t)addr); } } else { - DNBLogError("MachProcess::EnableBreakpoint ( breakID = %d ) no software breakpoint opcode for current architecture.", breakID); + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ) no software breakpoint opcode for current architecture.", (uint64_t)addr); } } } @@ -1114,16 +1041,16 @@ MachProcess::EnableBreakpoint(nub_break_t breakID) } bool -MachProcess::EnableWatchpoint(nub_watch_t watchID) +MachProcess::EnableWatchpoint(nub_addr_t addr) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::EnableWatchpoint(watchID = %d)", watchID); - DNBBreakpoint *wp = m_watchpoints.FindByID (watchID); + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::EnableWatchpoint(addr = 0x%8.8llx)", (uint64_t)addr); + DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); if (wp) { nub_addr_t addr = wp->Address(); if (wp->IsEnabled()) { - DNBLogWarning("MachProcess::EnableWatchpoint(watchID = %d) addr = 0x%8.8llx: watchpoint already enabled.", watchID, (uint64_t)addr); + DNBLogWarning("MachProcess::EnableWatchpoint(addr = 0x%8.8llx): watchpoint already enabled.", (uint64_t)addr); return true; } else diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h index ee2642ee474..7a52eaa54ae 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h @@ -114,22 +114,20 @@ public: //---------------------------------------------------------------------- // Breakpoint functions //---------------------------------------------------------------------- - nub_break_t CreateBreakpoint (nub_addr_t addr, nub_size_t length, bool hardware, thread_t thread); - bool DisableBreakpoint (nub_break_t breakID, bool remove); - nub_size_t DisableAllBreakpoints (bool remove); - bool EnableBreakpoint (nub_break_t breakID); - void DumpBreakpoint(nub_break_t breakID) const; + DNBBreakpoint * CreateBreakpoint (nub_addr_t addr, nub_size_t length, bool hardware); + bool DisableBreakpoint (nub_addr_t addr, bool remove); + void DisableAllBreakpoints (bool remove); + bool EnableBreakpoint (nub_addr_t addr); DNBBreakpointList& Breakpoints() { return m_breakpoints; } const DNBBreakpointList& Breakpoints() const { return m_breakpoints; } //---------------------------------------------------------------------- // Watchpoint functions //---------------------------------------------------------------------- - nub_watch_t CreateWatchpoint (nub_addr_t addr, nub_size_t length, uint32_t watch_type, bool hardware, thread_t thread); - bool DisableWatchpoint (nub_watch_t watchID, bool remove); - nub_size_t DisableAllWatchpoints (bool remove); - bool EnableWatchpoint (nub_watch_t watchID); - void DumpWatchpoint(nub_watch_t watchID) const; + DNBBreakpoint * CreateWatchpoint (nub_addr_t addr, nub_size_t length, uint32_t watch_type, bool hardware); + bool DisableWatchpoint (nub_addr_t addr, bool remove); + void DisableAllWatchpoints (bool remove); + bool EnableWatchpoint (nub_addr_t addr); uint32_t GetNumSupportedHardwareWatchpoints () const; DNBBreakpointList& Watchpoints() { return m_watchpoints; } const DNBBreakpointList& Watchpoints() const { return m_watchpoints; } @@ -263,7 +261,6 @@ private: void Clear (); void ReplyToAllExceptions (); void PrivateResume (); - nub_size_t RemoveTrapsFromBuffer (nub_addr_t addr, nub_size_t size, uint8_t *buf) const; uint32_t Flags () const { return m_flags; } nub_state_t DoSIGSTOP (bool clear_bps_and_wps, bool allow_running, uint32_t *thread_idx_ptr); diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index 61f5b21af14..a32161f4eb0 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -31,7 +31,6 @@ MachThread::MachThread (MachProcess *process, uint64_t unique_thread_id, thread_ m_seq_id (GetSequenceID()), m_state (eStateUnloaded), m_state_mutex (PTHREAD_MUTEX_RECURSIVE), - m_break_id (INVALID_NUB_BREAK_ID), m_suspend_count (0), m_stop_exception (), m_arch_ap (DNBArchProtocol::Create (this)), @@ -361,13 +360,12 @@ MachThread::Dump(uint32_t index) default: thread_run_state = "???"; break; } - DNBLogThreaded("[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 ", sp: 0x%16.16" PRIx64 ", breakID: %3d, user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d", + DNBLogThreaded("[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 ", sp: 0x%16.16" PRIx64 ", user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d", index, m_seq_id, m_unique_id, GetPC(INVALID_NUB_ADDRESS), GetSP(INVALID_NUB_ADDRESS), - m_break_id, m_basic_info.user_time.seconds, m_basic_info.user_time.microseconds, m_basic_info.system_time.seconds, m_basic_info.system_time.microseconds, m_basic_info.cpu_usage, @@ -406,35 +404,23 @@ MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action, bool ot m_stop_exception.Clear(); } -nub_break_t +DNBBreakpoint * MachThread::CurrentBreakpoint() { - return m_process->Breakpoints().FindIDByAddress(GetPC()); + return m_process->Breakpoints().FindByAddress(GetPC()); } bool MachThread::ShouldStop(bool &step_more) { // See if this thread is at a breakpoint? - nub_break_t breakID = CurrentBreakpoint(); + DNBBreakpoint *bp = CurrentBreakpoint(); - if (NUB_BREAK_ID_IS_VALID(breakID)) + if (bp) { // This thread is sitting at a breakpoint, ask the breakpoint // if we should be stopping here. - if (Process()->Breakpoints().ShouldStop(ProcessID(), ThreadID(), breakID)) - return true; - else - { - // The breakpoint said we shouldn't stop, but we may have gotten - // a signal or the user may have requested to stop in some other - // way. Stop if we have a valid exception (this thread won't if - // another thread was the reason this process stopped) and that - // exception, is NOT a breakpoint exception (a common case would - // be a SIGINT signal). - if (GetStopException().IsValid() && !GetStopException().IsBreakpoint()) - return true; - } + return true; } else { diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h index c6d7b312769..bf96e68bc6c 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h @@ -62,7 +62,7 @@ public: bool SetPC(uint64_t value); // Set program counter uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS); // Get stack pointer - nub_break_t CurrentBreakpoint(); + DNBBreakpoint * CurrentBreakpoint(); uint32_t EnableHardwareBreakpoint (const DNBBreakpoint *breakpoint); uint32_t EnableHardwareWatchpoint (const DNBBreakpoint *watchpoint); bool DisableHardwareBreakpoint (const DNBBreakpoint *breakpoint); @@ -125,7 +125,6 @@ protected: uint32_t m_seq_id; // A Sequential ID that increments with each new thread nub_state_t m_state; // The state of our process PThreadMutex m_state_mutex; // Multithreaded protection for m_state - nub_break_t m_break_id; // Breakpoint that this thread is (stopped)/was(running) at (NULL for none) struct thread_basic_info m_basic_info; // Basic information for a thread used to see if a thread is valid int32_t m_suspend_count; // The current suspend count > 0 means we have suspended m_suspendCount times, // < 0 means we have resumed it m_suspendCount times. diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp index 2ac171374f1..f549b4707d9 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp @@ -499,9 +499,9 @@ MachThreadList::EnableHardwareBreakpoint (const DNBBreakpoint* bp) const { if (bp != NULL) { - MachThreadSP thread_sp (GetThreadByID (bp->ThreadID())); - if (thread_sp) - return thread_sp->EnableHardwareBreakpoint(bp); + const uint32_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) + m_threads[idx]->EnableHardwareBreakpoint(bp); } return INVALID_NUB_HW_INDEX; } @@ -511,9 +511,9 @@ MachThreadList::DisableHardwareBreakpoint (const DNBBreakpoint* bp) const { if (bp != NULL) { - MachThreadSP thread_sp (GetThreadByID (bp->ThreadID())); - if (thread_sp) - return thread_sp->DisableHardwareBreakpoint(bp); + const uint32_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) + m_threads[idx]->DisableHardwareBreakpoint(bp); } return false; } diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp index 1d4a98fb742..4376e80b653 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp @@ -647,8 +647,8 @@ DNBArchImplI386::NotifyException(MachException::Data& exc) // Check for a breakpoint at one byte prior to the current PC value // since the PC will be just past the trap. - nub_break_t breakID = m_thread->Process()->Breakpoints().FindIDByAddress(pc); - if (NUB_BREAK_ID_IS_VALID(breakID)) + DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(pc); + if (bp) { // Backup the PC for i386 since the trap was taken and the PC // is at the address following the single byte trap instruction. diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 4a87aa2ce1a..aff76d881f1 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -602,8 +602,8 @@ DNBArchImplX86_64::NotifyException(MachException::Data& exc) // Check for a breakpoint at one byte prior to the current PC value // since the PC will be just past the trap. - nub_break_t breakID = m_thread->Process()->Breakpoints().FindIDByAddress(pc); - if (NUB_BREAK_ID_IS_VALID(breakID)) + DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(pc); + if (bp) { // Backup the PC for i386 since the trap was taken and the PC // is at the address following the single byte trap instruction. diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index d711a9710f4..e6b03033290 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -71,7 +71,6 @@ RNBRemote::RNBRemote () : m_rx_packets(), m_rx_partial_data(), m_rx_pthread(0), - m_breakpoints(), m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4), m_extended_mode(false), m_noack_mode(false), @@ -3252,32 +3251,16 @@ RNBRemote::HandlePacket_z (const char *p) { case '0': // set software breakpoint case '1': // set hardware breakpoint - { - // gdb can send multiple Z packets for the same address and - // these calls must be ref counted. - bool hardware = (break_type == '1'); - - // Check if we currently have a breakpoint already set at this address - BreakpointMapIter pos = m_breakpoints.find(addr); - if (pos != m_breakpoints.end()) - { - // We do already have a breakpoint at this address, increment - // its reference count and return OK - pos->second.Retain(); - return SendPacket ("OK"); - } - else { - // We do NOT already have a breakpoint at this address, So lets - // create one. - nub_break_t break_id = DNBBreakpointSet (pid, addr, byte_size, hardware); - if (NUB_BREAK_ID_IS_VALID(break_id)) + // gdb can send multiple Z packets for the same address and + // these calls must be ref counted. + bool hardware = (break_type == '1'); + + if (DNBBreakpointSet (pid, addr, byte_size, hardware)) { // We successfully created a breakpoint, now lets full out // a ref count structure with the breakID and add it to our // map. - Breakpoint rnbBreakpoint(break_id); - m_breakpoints[addr] = rnbBreakpoint; return SendPacket ("OK"); } else @@ -3286,43 +3269,23 @@ RNBRemote::HandlePacket_z (const char *p) return SendPacket ("E09"); } } - } break; case '2': // set write watchpoint case '3': // set read watchpoint case '4': // set access watchpoint - { - bool hardware = true; - uint32_t watch_flags = 0; - if (break_type == '2') - watch_flags = WATCH_TYPE_WRITE; - else if (break_type == '3') - watch_flags = WATCH_TYPE_READ; - else - watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE; - - // Check if we currently have a watchpoint already set at this address - BreakpointMapIter pos = m_watchpoints.find(addr); - if (pos != m_watchpoints.end()) - { - // We do already have a watchpoint at this address, increment - // its reference count and return OK - pos->second.Retain(); - return SendPacket ("OK"); - } - else { - // We do NOT already have a watchpoint at this address, So lets - // create one. - nub_watch_t watch_id = DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware); - if (NUB_WATCH_ID_IS_VALID(watch_id)) + bool hardware = true; + uint32_t watch_flags = 0; + if (break_type == '2') + watch_flags = WATCH_TYPE_WRITE; + else if (break_type == '3') + watch_flags = WATCH_TYPE_READ; + else + watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE; + + if (DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware)) { - // We successfully created a watchpoint, now lets full out - // a ref count structure with the watch_id and add it to our - // map. - Breakpoint rnbWatchpoint(watch_id); - m_watchpoints[addr] = rnbWatchpoint; return SendPacket ("OK"); } else @@ -3331,7 +3294,6 @@ RNBRemote::HandlePacket_z (const char *p) return SendPacket ("E09"); } } - } break; default: @@ -3345,83 +3307,27 @@ RNBRemote::HandlePacket_z (const char *p) { case '0': // remove software breakpoint case '1': // remove hardware breakpoint - { - // gdb can send multiple z packets for the same address and - // these calls must be ref counted. - BreakpointMapIter pos = m_breakpoints.find(addr); - if (pos != m_breakpoints.end()) + if (DNBBreakpointClear (pid, addr)) { - // We currently have a breakpoint at address ADDR. Decrement - // its reference count, and it that count is now zero we - // can clear the breakpoint. - pos->second.Release(); - if (pos->second.RefCount() == 0) - { - if (DNBBreakpointClear (pid, pos->second.BreakID())) - { - m_breakpoints.erase(pos); - return SendPacket ("OK"); - } - else - { - return SendPacket ("E08"); - } - } - else - { - // We still have references to this breakpoint don't - // delete it, just decrementing the reference count - // is enough. - return SendPacket ("OK"); - } + return SendPacket ("OK"); } else { - // We don't know about any breakpoints at this address return SendPacket ("E08"); } - } break; case '2': // remove write watchpoint case '3': // remove read watchpoint case '4': // remove access watchpoint - { - // gdb can send multiple z packets for the same address and - // these calls must be ref counted. - BreakpointMapIter pos = m_watchpoints.find(addr); - if (pos != m_watchpoints.end()) + if (DNBWatchpointClear (pid, addr)) { - // We currently have a watchpoint at address ADDR. Decrement - // its reference count, and it that count is now zero we - // can clear the watchpoint. - pos->second.Release(); - if (pos->second.RefCount() == 0) - { - if (DNBWatchpointClear (pid, pos->second.BreakID())) - { - m_watchpoints.erase(pos); - return SendPacket ("OK"); - } - else - { - return SendPacket ("E08"); - } - } - else - { - // We still have references to this watchpoint don't - // delete it, just decrementing the reference count - // is enough. - return SendPacket ("OK"); - } + return SendPacket ("OK"); } else { - // We don't know about any watchpoints at this address return SendPacket ("E08"); } - } break; default: diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h index b8b3b255f4f..15d725ce4cd 100644 --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -301,39 +301,6 @@ protected: nub_thread_t ExtractThreadIDFromThreadSuffix (const char *p); - // gdb can send multiple Z/z packets for the same address and - // these calls must be ref counted. - struct Breakpoint - { - Breakpoint(nub_break_t breakID) : - m_breakID(breakID), - m_refCount(1) - { - } - - Breakpoint() : - m_breakID(INVALID_NUB_BREAK_ID), - m_refCount(0) - { - } - - Breakpoint(const Breakpoint& rhs) : - m_breakID(rhs.m_breakID), - m_refCount(rhs.m_refCount) - { - } - - nub_break_t BreakID() const { return m_breakID; } - uint32_t RefCount() const { return m_refCount; } - void Release() { if (m_refCount > 0) --m_refCount; } - void Retain() { ++m_refCount; } - - nub_break_t m_breakID; - uint32_t m_refCount; - }; - typedef std::map<nub_addr_t, Breakpoint> BreakpointMap; - typedef BreakpointMap::iterator BreakpointMapIter; - typedef BreakpointMap::const_iterator BreakpointMapConstIter; RNBContext m_ctx; // process context RNBSocket m_comm; // communication port std::string m_arch; @@ -345,8 +312,6 @@ protected: std::deque<std::string> m_rx_packets; std::string m_rx_partial_data; // For packets that may come in more than one batch, anything left over can be left here pthread_t m_rx_pthread; - BreakpointMap m_breakpoints; - BreakpointMap m_watchpoints; uint32_t m_max_payload_size; // the maximum sized payload we should send to gdb bool m_extended_mode; // are we in extended mode? bool m_noack_mode; // are we in no-ack mode? |