Index: stable/10/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp =================================================================== --- stable/10/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp (revision 263368) +++ stable/10/contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp (revision 263369) @@ -1,348 +1,345 @@ //===-- BreakpointLocationList.cpp ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocationList.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) : m_owner (owner), m_locations(), m_address_to_location (), m_mutex (Mutex::eMutexTypeRecursive), m_next_id (0), m_new_location_recorder (NULL) { } BreakpointLocationList::~BreakpointLocationList() { } BreakpointLocationSP BreakpointLocationList::Create (const Address &addr) { Mutex::Locker locker (m_mutex); // The location ID is just the size of the location list + 1 lldb::break_id_t bp_loc_id = ++m_next_id; BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware())); m_locations.push_back (bp_loc_sp); m_address_to_location[addr] = bp_loc_sp; return bp_loc_sp; } bool BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id) { BreakpointLocationSP bp = FindByID (break_id); if (bp) { // Let the BreakpointLocation 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->ShouldStop (context); } // We should stop here since this BreakpointLocation isn't valid anymore or it // doesn't exist. return true; } lldb::break_id_t BreakpointLocationList::FindIDByAddress (const Address &addr) { BreakpointLocationSP bp_loc_sp = FindByAddress (addr); if (bp_loc_sp) { return bp_loc_sp->GetID(); } return LLDB_INVALID_BREAK_ID; } static bool Compare (BreakpointLocationSP lhs, lldb::break_id_t val) { return lhs->GetID() < val; } BreakpointLocationSP BreakpointLocationList::FindByID (lldb::break_id_t break_id) const { - BreakpointLocationSP bp_loc_sp; Mutex::Locker locker (m_mutex); - - collection::const_iterator begin = m_locations.begin(), end = m_locations.end(); - collection::const_iterator result; - result = std::lower_bound(begin, end, break_id, Compare); - if (result == end) - return bp_loc_sp; + collection::const_iterator end = m_locations.end(); + collection::const_iterator pos = std::lower_bound(m_locations.begin(), end, break_id, Compare); + if (pos != end && (*pos)->GetID() == break_id) + return *(pos); else - return *(result); + return BreakpointLocationSP(); } size_t BreakpointLocationList::FindInModule (Module *module, BreakpointLocationCollection& bp_loc_list) { Mutex::Locker locker (m_mutex); const size_t orig_size = bp_loc_list.GetSize(); collection::iterator pos, end = m_locations.end(); for (pos = m_locations.begin(); pos != end; ++pos) { BreakpointLocationSP break_loc = (*pos); SectionSP section_sp (break_loc->GetAddress().GetSection()); if (section_sp && section_sp->GetModule().get() == module) { bp_loc_list.Add (break_loc); } } return bp_loc_list.GetSize() - orig_size; } const BreakpointLocationSP BreakpointLocationList::FindByAddress (const Address &addr) const { Mutex::Locker locker (m_mutex); BreakpointLocationSP bp_loc_sp; if (!m_locations.empty()) { Address so_addr; if (addr.IsSectionOffset()) { so_addr = addr; } else { // Try and resolve as a load address if possible. m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr); if (!so_addr.IsValid()) { // The address didn't resolve, so just set to passed in addr. so_addr = addr; } } addr_map::const_iterator pos = m_address_to_location.find (so_addr); if (pos != m_address_to_location.end()) bp_loc_sp = pos->second; } return bp_loc_sp; } void BreakpointLocationList::Dump (Stream *s) const { s->Printf("%p: ", this); //s->Indent(); Mutex::Locker locker (m_mutex); s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size()); s->IndentMore(); collection::const_iterator pos, end = m_locations.end(); for (pos = m_locations.begin(); pos != end; ++pos) (*pos).get()->Dump(s); s->IndentLess(); } BreakpointLocationSP BreakpointLocationList::GetByIndex (size_t i) { Mutex::Locker locker (m_mutex); BreakpointLocationSP bp_loc_sp; if (i < m_locations.size()) bp_loc_sp = m_locations[i]; return bp_loc_sp; } const BreakpointLocationSP BreakpointLocationList::GetByIndex (size_t i) const { Mutex::Locker locker (m_mutex); BreakpointLocationSP bp_loc_sp; if (i < m_locations.size()) bp_loc_sp = m_locations[i]; return bp_loc_sp; } void BreakpointLocationList::ClearAllBreakpointSites () { Mutex::Locker locker (m_mutex); collection::iterator pos, end = m_locations.end(); for (pos = m_locations.begin(); pos != end; ++pos) (*pos)->ClearBreakpointSite(); } void BreakpointLocationList::ResolveAllBreakpointSites () { Mutex::Locker locker (m_mutex); collection::iterator pos, end = m_locations.end(); for (pos = m_locations.begin(); pos != end; ++pos) { if ((*pos)->IsEnabled()) (*pos)->ResolveBreakpointSite(); } } uint32_t BreakpointLocationList::GetHitCount () const { uint32_t hit_count = 0; Mutex::Locker locker (m_mutex); collection::const_iterator pos, end = m_locations.end(); for (pos = m_locations.begin(); pos != end; ++pos) hit_count += (*pos)->GetHitCount(); return hit_count; } size_t BreakpointLocationList::GetNumResolvedLocations() const { Mutex::Locker locker (m_mutex); size_t resolve_count = 0; collection::const_iterator pos, end = m_locations.end(); for (pos = m_locations.begin(); pos != end; ++pos) { if ((*pos)->IsResolved()) ++resolve_count; } return resolve_count; } void BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level) { Mutex::Locker locker (m_mutex); collection::iterator pos, end = m_locations.end(); for (pos = m_locations.begin(); pos != end; ++pos) { s->Printf(" "); (*pos)->GetDescription(s, level); } } BreakpointLocationSP BreakpointLocationList::AddLocation (const Address &addr, bool *new_location) { Mutex::Locker locker (m_mutex); if (new_location) *new_location = false; BreakpointLocationSP bp_loc_sp (FindByAddress(addr)); if (!bp_loc_sp) { bp_loc_sp = Create (addr); if (bp_loc_sp) { bp_loc_sp->ResolveBreakpointSite(); if (new_location) *new_location = true; if(m_new_location_recorder) { m_new_location_recorder->Add(bp_loc_sp); } } } return bp_loc_sp; } bool BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp) { if (bp_loc_sp) { Mutex::Locker locker (m_mutex); m_address_to_location.erase (bp_loc_sp->GetAddress()); collection::iterator pos, end = m_locations.end(); for (pos = m_locations.begin(); pos != end; ++pos) { if ((*pos).get() == bp_loc_sp.get()) { m_locations.erase (pos); return true; } } } return false; } void BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch) { Mutex::Locker locker (m_mutex); size_t idx = 0; // Don't cache m_location.size() as it will change since we might // remove locations from our vector... while (idx < m_locations.size()) { BreakpointLocation *bp_loc = m_locations[idx].get(); if (bp_loc->GetAddress().SectionWasDeleted()) { // Section was deleted which means this breakpoint comes from a module // that is no longer valid, so we should remove it. m_locations.erase(m_locations.begin() + idx); continue; } if (arch.IsValid()) { ModuleSP module_sp (bp_loc->GetAddress().GetModule()); if (module_sp) { if (!arch.IsCompatibleMatch(module_sp->GetArchitecture())) { // The breakpoint was in a module whose architecture is no longer // compatible with "arch", so we need to remove it m_locations.erase(m_locations.begin() + idx); continue; } } } // Only increment the index if we didn't remove the locations at index "idx" ++idx; } } void BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations) { Mutex::Locker locker (m_mutex); assert (m_new_location_recorder == NULL); m_new_location_recorder = &new_locations; } void BreakpointLocationList::StopRecordingNewLocations () { Mutex::Locker locker (m_mutex); m_new_location_recorder = NULL; } Index: stable/10/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp =================================================================== --- stable/10/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp (revision 263368) +++ stable/10/contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp (revision 263369) @@ -1,461 +1,485 @@ //===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; bool UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const { if (m_type == rhs.m_type) { switch (m_type) { case unspecified: case undefined: case same: return true; case atCFAPlusOffset: case isCFAPlusOffset: return m_location.offset == rhs.m_location.offset; case inOtherRegister: return m_location.reg_num == rhs.m_location.reg_num; case atDWARFExpression: case isDWARFExpression: if (m_location.expr.length == rhs.m_location.expr.length) return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length); break; } } return false; } // This function doesn't copy the dwarf expression bytes; they must remain in allocated // memory for the lifespan of this UnwindPlan object. void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len) { m_type = atDWARFExpression; m_location.expr.opcodes = opcodes; m_location.expr.length = len; } // This function doesn't copy the dwarf expression bytes; they must remain in allocated // memory for the lifespan of this UnwindPlan object. void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len) { m_type = isDWARFExpression; m_location.expr.opcodes = opcodes; m_location.expr.length = len; } void UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_plan, const UnwindPlan::Row* row, Thread* thread, bool verbose) const { switch (m_type) { case unspecified: if (verbose) s.PutCString ("="); else s.PutCString ("=!"); break; case undefined: if (verbose) s.PutCString ("="); else s.PutCString ("=?"); break; case same: s.PutCString ("= "); break; case atCFAPlusOffset: case isCFAPlusOffset: { s.PutChar('='); if (m_type == atCFAPlusOffset) s.PutChar('['); if (verbose) s.Printf ("CFA%+d", m_location.offset); if (unwind_plan && row) { const uint32_t cfa_reg = row->GetCFARegister(); const RegisterInfo *cfa_reg_info = unwind_plan->GetRegisterInfo (thread, cfa_reg); const int32_t offset = row->GetCFAOffset() + m_location.offset; if (verbose) { if (cfa_reg_info) s.Printf (" (%s%+d)", cfa_reg_info->name, offset); else s.Printf (" (reg(%u)%+d)", cfa_reg, offset); } else { if (cfa_reg_info) s.Printf ("%s", cfa_reg_info->name); else s.Printf ("reg(%u)", cfa_reg); if (offset != 0) s.Printf ("%+d", offset); } } if (m_type == atCFAPlusOffset) s.PutChar(']'); } break; case inOtherRegister: { const RegisterInfo *other_reg_info = NULL; if (unwind_plan) other_reg_info = unwind_plan->GetRegisterInfo (thread, m_location.reg_num); if (other_reg_info) s.Printf ("=%s", other_reg_info->name); else s.Printf ("=reg(%u)", m_location.reg_num); } break; case atDWARFExpression: case isDWARFExpression: { s.PutChar('='); if (m_type == atDWARFExpression) s.PutCString("[dwarf-expr]"); else s.PutCString("dwarf-expr"); } break; } } void UnwindPlan::Row::Clear () { m_offset = 0; m_cfa_reg_num = LLDB_INVALID_REGNUM; m_cfa_offset = 0; m_register_locations.clear(); } void UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const { const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, GetCFARegister()); if (base_addr != LLDB_INVALID_ADDRESS) s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); else s.Printf ("0x%8.8" PRIx64 ": CFA=", GetOffset()); if (reg_info) s.Printf ("%s", reg_info->name); else s.Printf ("reg(%u)", GetCFARegister()); s.Printf ("%+3d => ", GetCFAOffset ()); for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx) { reg_info = unwind_plan->GetRegisterInfo (thread, idx->first); if (reg_info) s.Printf ("%s", reg_info->name); else s.Printf ("reg(%u)", idx->first); const bool verbose = false; idx->second.Dump(s, unwind_plan, this, thread, verbose); s.PutChar (' '); } s.EOL(); } UnwindPlan::Row::Row() : m_offset(0), m_cfa_reg_num(LLDB_INVALID_REGNUM), m_cfa_offset(0), m_register_locations() { } bool UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const { collection::const_iterator pos = m_register_locations.find(reg_num); if (pos != m_register_locations.end()) { register_location = pos->second; return true; } return false; } void UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location) { m_register_locations[reg_num] = register_location; } bool UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace) { if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) return false; RegisterLocation reg_loc; reg_loc.SetAtCFAPlusOffset(offset); m_register_locations[reg_num] = reg_loc; return true; } bool UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace) { if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) return false; RegisterLocation reg_loc; reg_loc.SetIsCFAPlusOffset(offset); m_register_locations[reg_num] = reg_loc; return true; } bool UnwindPlan::Row::SetRegisterLocationToUndefined (uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) { collection::iterator pos = m_register_locations.find(reg_num); collection::iterator end = m_register_locations.end(); if (pos != end) { if (!can_replace) return false; if (can_replace_only_if_unspecified && !pos->second.IsUnspecified()) return false; } RegisterLocation reg_loc; reg_loc.SetUndefined(); m_register_locations[reg_num] = reg_loc; return true; } bool UnwindPlan::Row::SetRegisterLocationToUnspecified (uint32_t reg_num, bool can_replace) { if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) return false; RegisterLocation reg_loc; reg_loc.SetUnspecified(); m_register_locations[reg_num] = reg_loc; return true; } bool UnwindPlan::Row::SetRegisterLocationToRegister (uint32_t reg_num, uint32_t other_reg_num, bool can_replace) { if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) return false; RegisterLocation reg_loc; reg_loc.SetInRegister(other_reg_num); m_register_locations[reg_num] = reg_loc; return true; } bool UnwindPlan::Row::SetRegisterLocationToSame (uint32_t reg_num, bool must_replace) { if (must_replace && m_register_locations.find(reg_num) == m_register_locations.end()) return false; RegisterLocation reg_loc; reg_loc.SetSame(); m_register_locations[reg_num] = reg_loc; return true; } void UnwindPlan::Row::SetCFARegister (uint32_t reg_num) { m_cfa_reg_num = reg_num; } bool UnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const { if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset) return false; return m_register_locations == rhs.m_register_locations; } void UnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp) { if (m_row_list.empty() || m_row_list.back()->GetOffset() != row_sp->GetOffset()) m_row_list.push_back(row_sp); else m_row_list.back() = row_sp; } UnwindPlan::RowSP UnwindPlan::GetRowForFunctionOffset (int offset) const { RowSP row; if (!m_row_list.empty()) { if (offset == -1) row = m_row_list.back(); else { collection::const_iterator pos, end = m_row_list.end(); for (pos = m_row_list.begin(); pos != end; ++pos) { if ((*pos)->GetOffset() <= offset) row = *pos; else break; } } } return row; } bool UnwindPlan::IsValidRowIndex (uint32_t idx) const { return idx < m_row_list.size(); } const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex (uint32_t idx) const { // You must call IsValidRowIndex(idx) first before calling this!!! assert (idx < m_row_list.size()); return m_row_list[idx]; } const UnwindPlan::RowSP UnwindPlan::GetLastRow () const { // You must call GetRowCount() first to make sure there is at least one row assert (!m_row_list.empty()); return m_row_list.back(); } int UnwindPlan::GetRowCount () const { return m_row_list.size (); } void UnwindPlan::SetPlanValidAddressRange (const AddressRange& range) { if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0) m_plan_valid_address_range = range; } bool UnwindPlan::PlanValidAtAddress (Address addr) { // If this UnwindPlan has no rows, it is an invalid UnwindPlan. if (GetRowCount() == 0) { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (log) - log->Printf ("Testing if UnwindPlan is valid at pc 0x%" PRIx64 ": No unwind rows - is invalid."); + { + StreamString s; + if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset)) + { + log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s' at address %s", + m_source_name.GetCString(), s.GetData()); + } + else + { + log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'", + m_source_name.GetCString()); + } + } return false; } // If the 0th Row of unwind instructions is missing, or if it doesn't provide // a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan. if (GetRowAtIndex(0).get() == NULL || GetRowAtIndex(0)->GetCFARegister() == LLDB_INVALID_REGNUM) { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (log) - log->Printf ("Testing if UnwindPlan is valid at pc 0x%" PRIx64 ": No CFA register - is invalid."); + { + StreamString s; + if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset)) + { + log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s' at address %s", + m_source_name.GetCString(), s.GetData()); + } + else + { + log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s'", + m_source_name.GetCString()); + } + } return false; } if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0) return true; if (!addr.IsValid()) return true; if (m_plan_valid_address_range.ContainsFileAddress (addr)) return true; return false; } void UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const { if (!m_source_name.IsEmpty()) { s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString()); } if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0) { s.PutCString ("Address range of this UnwindPlan: "); TargetSP target_sp(thread->CalculateTarget()); m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset); s.EOL(); } collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end(); for (pos = begin; pos != end; ++pos) { s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos)); (*pos)->Dump(s, this, thread, base_addr); } } void UnwindPlan::SetSourceName (const char *source) { m_source_name = ConstString (source); } ConstString UnwindPlan::GetSourceName () const { return m_source_name; } const RegisterInfo * UnwindPlan::GetRegisterInfo (Thread* thread, uint32_t unwind_reg) const { if (thread) { RegisterContext *reg_ctx = thread->GetRegisterContext().get(); if (reg_ctx) { uint32_t reg; if (m_register_kind == eRegisterKindLLDB) reg = unwind_reg; else reg = reg_ctx->ConvertRegisterKindToRegisterNumber (m_register_kind, unwind_reg); if (reg != LLDB_INVALID_REGNUM) return reg_ctx->GetRegisterInfoAtIndex (reg); } } return NULL; } Index: stable/10 =================================================================== --- stable/10 (revision 263368) +++ stable/10 (revision 263369) Property changes on: stable/10 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r258897