diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/API/SBTarget.cpp | 35 | ||||
-rw-r--r-- | lldb/source/Breakpoint/BreakpointResolverAddress.cpp | 90 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectBreakpoint.cpp | 38 | ||||
-rw-r--r-- | lldb/source/Target/Target.cpp | 13 |
4 files changed, 153 insertions, 23 deletions
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 8a63ea304bb..c7595c3c39f 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -1053,6 +1053,41 @@ SBTarget::BreakpointCreateByAddress (addr_t address) return sb_bp; } +SBBreakpoint +SBTarget::BreakpointCreateBySBAddress (SBAddress &sb_address) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + SBBreakpoint sb_bp; + TargetSP target_sp(GetSP()); + if (!sb_address.IsValid()) + { + if (log) + log->Printf ("SBTarget(%p)::BreakpointCreateBySBAddress called with invalid address", + static_cast<void*>(target_sp.get())); + return sb_bp; + } + + if (target_sp) + { + Mutex::Locker api_locker (target_sp->GetAPIMutex()); + const bool hardware = false; + *sb_bp = target_sp->CreateBreakpoint (sb_address.ref(), false, hardware); + } + + if (log) + { + SBStream s; + sb_address.GetDescription(s); + log->Printf ("SBTarget(%p)::BreakpointCreateBySBAddress (address=%s) => SBBreakpoint(%p)", + static_cast<void*>(target_sp.get()), + s.GetData(), + static_cast<void*>(sb_bp.get())); + } + + return sb_bp; +} + lldb::SBBreakpoint SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::SBFileSpec &source_file, diff --git a/lldb/source/Breakpoint/BreakpointResolverAddress.cpp b/lldb/source/Breakpoint/BreakpointResolverAddress.cpp index 193bc413af0..8a0469a07e4 100644 --- a/lldb/source/Breakpoint/BreakpointResolverAddress.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverAddress.cpp @@ -16,6 +16,7 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -29,10 +30,25 @@ using namespace lldb_private; BreakpointResolverAddress::BreakpointResolverAddress ( Breakpoint *bkpt, + const Address &addr, + const FileSpec &module_spec +) : + BreakpointResolver (bkpt, BreakpointResolver::AddressResolver), + m_addr (addr), + m_resolved_addr(LLDB_INVALID_ADDRESS), + m_module_filespec(module_spec) +{ +} + +BreakpointResolverAddress::BreakpointResolverAddress +( + Breakpoint *bkpt, const Address &addr ) : BreakpointResolver (bkpt, BreakpointResolver::AddressResolver), - m_addr (addr) + m_addr (addr), + m_resolved_addr(LLDB_INVALID_ADDRESS), + m_module_filespec() { } @@ -44,10 +60,16 @@ BreakpointResolverAddress::~BreakpointResolverAddress () void BreakpointResolverAddress::ResolveBreakpoint (SearchFilter &filter) { - // The address breakpoint only takes once, so if we've already set it we're done. - if (m_breakpoint->GetNumLocations() > 0) - return; - else + // If the address is not section relative, then we should not try to re-resolve it, it is just some + // random address and we wouldn't know what to do on reload. But if it is section relative, we need to + // re-resolve it since the section it's in may have shifted on re-run. + bool re_resolve = false; + if (m_addr.GetSection() || m_module_filespec) + re_resolve = true; + else if (m_breakpoint->GetNumLocations() == 0) + re_resolve = true; + + if (re_resolve) BreakpointResolver::ResolveBreakpoint(filter); } @@ -58,10 +80,14 @@ BreakpointResolverAddress::ResolveBreakpointInModules ModuleList &modules ) { - // The address breakpoint only takes once, so if we've already set it we're done. - if (m_breakpoint->GetNumLocations() > 0) - return; - else + // See comment in ResolveBreakpoint. + bool re_resolve = false; + if (m_addr.GetSection()) + re_resolve = true; + else if (m_breakpoint->GetNumLocations() == 0) + re_resolve = true; + + if (re_resolve) BreakpointResolver::ResolveBreakpointInModules (filter, modules); } @@ -78,14 +104,44 @@ BreakpointResolverAddress::SearchCallback if (filter.AddressPasses (m_addr)) { - BreakpointLocationSP bp_loc_sp(m_breakpoint->AddLocation(m_addr)); - if (bp_loc_sp && !m_breakpoint->IsInternal()) + if (m_breakpoint->GetNumLocations() == 0) + { + // If the address is just an offset, and we're given a module, see if we can find the appropriate module + // loaded in the binary, and fix up m_addr to use that. + if (!m_addr.IsSectionOffset() && m_module_filespec) + { + Target &target = m_breakpoint->GetTarget(); + ModuleSpec module_spec(m_module_filespec); + ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec); + if (module_sp) + { + Address tmp_address; + if (module_sp->ResolveFileAddress(m_addr.GetOffset(), tmp_address)) + m_addr = tmp_address; + } + } + + BreakpointLocationSP bp_loc_sp(m_breakpoint->AddLocation(m_addr)); + m_resolved_addr = m_addr.GetLoadAddress(&m_breakpoint->GetTarget()); + if (bp_loc_sp && !m_breakpoint->IsInternal()) + { + StreamString s; + bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("Added location: %s\n", s.GetData()); + } + } + else { - StreamString s; - bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("Added location: %s\n", s.GetData()); + BreakpointLocationSP loc_sp = m_breakpoint->GetLocationAtIndex(0); + lldb::addr_t cur_load_location = m_addr.GetLoadAddress(&m_breakpoint->GetTarget()); + if (cur_load_location != m_resolved_addr) + { + m_resolved_addr = cur_load_location; + loc_sp->ClearBreakpointSite(); + loc_sp->ResolveBreakpointSite(); + } } } return Searcher::eCallbackReturnStop; @@ -101,7 +157,7 @@ void BreakpointResolverAddress::GetDescription (Stream *s) { s->PutCString ("address = "); - m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(), Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); + m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(), Address::DumpStyleModuleWithFileAddress, Address::DumpStyleLoadAddress); } void diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index edd733667d6..bb59e1f82e8 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -507,11 +507,32 @@ protected: break; case eSetTypeAddress: // Breakpoint by address - bp = target->CreateBreakpoint (m_options.m_load_addr, - internal, - m_options.m_hardware).get(); + { + // If a shared library has been specified, make an lldb_private::Address with the library, and + // use that. That way the address breakpoint will track the load location of the library. + size_t num_modules_specified = m_options.m_modules.GetSize(); + if (num_modules_specified == 1) + { + const FileSpec *file_spec = m_options.m_modules.GetFileSpecPointerAtIndex(0); + bp = target->CreateAddressInModuleBreakpoint (m_options.m_load_addr, + internal, + file_spec, + m_options.m_hardware).get(); + } + else if (num_modules_specified == 0) + { + bp = target->CreateBreakpoint (m_options.m_load_addr, + internal, + m_options.m_hardware).get(); + } + else + { + result.AppendError("Only one shared library can be specified for address breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } break; - + } case eSetTypeFunctionName: // Breakpoint by function name { uint32_t name_type_mask = m_options.m_func_name_type_mask; @@ -766,7 +787,14 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = // "Set the breakpoint by source location at this particular column."}, { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, - "Set the breakpoint by address, at the specified address."}, + "Set the breakpoint at the specified address. " + "If the address maps uniquely to a particular " + "binary, then the address will be converted to a \"file\" address, so that the breakpoint will track that binary+offset no matter where " + "the binary eventually loads. " + "Alternately, if you also specify the module - with the -s option - then the address will be treated as " + "a file address in that module, and resolved accordingly. Again, this will allow lldb to track that offset on " + "subsequent reloads. The module need not have been loaded at the time you specify this breakpoint, and will " + "get resolved when the module is loaded."}, { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make one breakpoint for multiple names" }, diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 86b6b99b0e7..aa423fb43ce 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -417,13 +417,24 @@ Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware) } BreakpointSP -Target::CreateBreakpoint (Address &addr, bool internal, bool hardware) +Target::CreateBreakpoint (const Address &addr, bool internal, bool hardware) { SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches (shared_from_this())); BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, addr)); return CreateBreakpoint (filter_sp, resolver_sp, internal, hardware, false); } +lldb::BreakpointSP +Target::CreateAddressInModuleBreakpoint (lldb::addr_t file_addr, + bool internal, + const FileSpec *file_spec, + bool request_hardware) +{ + SearchFilterSP filter_sp(new SearchFilterForUnconstrainedSearches (shared_from_this())); + BreakpointResolverSP resolver_sp (new BreakpointResolverAddress (NULL, file_addr, file_spec)); + return CreateBreakpoint (filter_sp, resolver_sp, internal, request_hardware, false); +} + BreakpointSP Target::CreateBreakpoint (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles, |