For logical backtrace work, lldb needs to track Module unloads etc & symoblicate an address based on a point in time

<rdar://problem/15314403> 

This patch adds a new lldb_private::SectionLoadHistory class that tracks what shared libraries were loaded given a process stop ID. This allows us to keep a history of the sections that were loaded for a time T. Many items in history objects will rely upon the process stop ID in the future.

llvm-svn: 196557
This commit is contained in:
Greg Clayton
2013-12-06 01:12:00 +00:00
parent d0b171103e
commit d5944cd118
32 changed files with 532 additions and 48 deletions

View File

@@ -646,9 +646,47 @@ public:
void
Clear ();
//------------------------------------------------------------------
/// Resolve a current load address into a section offset address.
///
/// @param[in] vm_addr
/// A virtual address from the current process state that is to
/// be translated into a section offset address.
///
/// @return
/// An SBAddress which will be valid if \a vm_addr was
/// successfully resolved into a section offset address, or an
/// invalid SBAddress if \a vm_addr doesn't resolve to a section
/// in a module.
//------------------------------------------------------------------
lldb::SBAddress
ResolveLoadAddress (lldb::addr_t vm_addr);
//------------------------------------------------------------------
/// Resolve a current load address into a section offset address
/// using the process stop ID to identify a time in the past.
///
/// @param[in] stop_id
/// Each time a process stops, the process stop ID integer gets
/// incremented. These stop IDs are used to identify past times
/// and can be used in history objects as a cheap way to store
/// the time at which the sample was taken. Specifying
/// UINT32_MAX will always resolve the address using the
/// currently loaded sections.
///
/// @param[in] vm_addr
/// A virtual address from the current process state that is to
/// be translated into a section offset address.
///
/// @return
/// An SBAddress which will be valid if \a vm_addr was
/// successfully resolved into a section offset address, or an
/// invalid SBAddress if \a vm_addr doesn't resolve to a section
/// in a module.
//------------------------------------------------------------------
lldb::SBAddress
ResolvePastLoadAddress (uint32_t stop_id, lldb::addr_t vm_addr);
SBSymbolContext
ResolveSymbolContextForAddress (const SBAddress& addr,
uint32_t resolve_scope);

View File

@@ -0,0 +1,109 @@
//===-- SectionLoadHistory.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_SectionLoadHistory_h_
#define liblldb_SectionLoadHistory_h_
// C Includes
// C++ Includes
#include <map>
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Host/Mutex.h"
namespace lldb_private {
class SectionLoadHistory
{
public:
enum {
// Pass eStopIDNow to any function that takes a stop ID to get
// the current value.
eStopIDNow = UINT32_MAX
};
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
SectionLoadHistory () :
m_stop_id_to_section_load_list(),
m_mutex (Mutex::eMutexTypeRecursive)
{
}
~SectionLoadHistory()
{
// Call clear since this takes a lock and clears the section load list
// in case another thread is currently using this section load list
Clear();
}
SectionLoadList &
GetCurrentSectionLoadList ();
bool
IsEmpty() const;
void
Clear ();
uint32_t
GetLastStopID() const;
// Get the section load address given a process stop ID
lldb::addr_t
GetSectionLoadAddress (uint32_t stop_id,
const lldb::SectionSP &section_sp);
bool
ResolveLoadAddress (uint32_t stop_id,
lldb::addr_t load_addr,
Address &so_addr);
bool
SetSectionLoadAddress (uint32_t stop_id,
const lldb::SectionSP &section_sp,
lldb::addr_t load_addr,
bool warn_multiple = false);
// The old load address should be specified when unloading to ensure we get
// the correct instance of the section as a shared library could be loaded
// at more than one location.
bool
SetSectionUnloaded (uint32_t stop_id,
const lldb::SectionSP &section_sp,
lldb::addr_t load_addr);
// Unload all instances of a section. This function can be used on systems
// that don't support multiple copies of the same shared library to be
// loaded at the same time.
size_t
SetSectionUnloaded (uint32_t stop_id,
const lldb::SectionSP &section_sp);
void
Dump (Stream &s,
Target *target);
protected:
SectionLoadList *
GetSectionLoadListForStopID (uint32_t stop_id, bool read_only);
typedef std::map<uint32_t, lldb::SectionLoadListSP> StopIDToSectionLoadList;
StopIDToSectionLoadList m_stop_id_to_section_load_list;
mutable Mutex m_mutex;
private:
DISALLOW_COPY_AND_ASSIGN (SectionLoadHistory);
};
} // namespace lldb_private
#endif // liblldb_SectionLoadHistory_h_

View File

@@ -36,6 +36,8 @@ public:
{
}
SectionLoadList (const SectionLoadList& rhs);
~SectionLoadList()
{
// Call clear since this takes a lock and clears the section load list
@@ -43,6 +45,9 @@ public:
Clear();
}
void
operator=(const SectionLoadList &rhs);
bool
IsEmpty() const;
@@ -79,9 +84,6 @@ protected:
addr_to_sect_collection m_addr_to_sect;
sect_to_addr_collection m_sect_to_addr;
mutable Mutex m_mutex;
private:
DISALLOW_COPY_AND_ASSIGN (SectionLoadList);
};
} // namespace lldb_private

View File

@@ -35,7 +35,7 @@
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/PathMappingList.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/SectionLoadHistory.h"
namespace lldb_private {
@@ -1001,14 +1001,14 @@ public:
SectionLoadList&
GetSectionLoadList()
{
return m_section_load_list;
return m_section_load_history.GetCurrentSectionLoadList();
}
const SectionLoadList&
GetSectionLoadList() const
{
return m_section_load_list;
}
// const SectionLoadList&
// GetSectionLoadList() const
// {
// return const_cast<SectionLoadHistory *>(&m_section_load_history)->GetCurrentSectionLoadList();
// }
static Target *
GetTargetFromContexts (const ExecutionContext *exe_ctx_ptr,
@@ -1048,6 +1048,26 @@ public:
Error
Install(ProcessLaunchInfo *launch_info);
bool
ResolveLoadAddress (lldb::addr_t load_addr,
Address &so_addr,
uint32_t stop_id = SectionLoadHistory::eStopIDNow);
bool
SetSectionLoadAddress (const lldb::SectionSP &section,
lldb::addr_t load_addr,
bool warn_multiple = false);
bool
SetSectionUnloaded (const lldb::SectionSP &section_sp);
bool
SetSectionUnloaded (const lldb::SectionSP &section_sp, lldb::addr_t load_addr);
void
ClearAllLoadedSections ();
// Since expressions results can persist beyond the lifetime of a process,
// and the const expression results are available after a process is gone,
// we provide a way for expressions to be evaluated from the Target itself.
@@ -1250,7 +1270,7 @@ protected:
Mutex m_mutex; ///< An API mutex that is used by the lldb::SB* classes make the SB interface thread safe
ArchSpec m_arch;
ModuleList m_images; ///< The list of images for this process (shared libraries and anything dynamically loaded).
SectionLoadList m_section_load_list;
SectionLoadHistory m_section_load_history;
BreakpointList m_breakpoint_list;
BreakpointList m_internal_breakpoint_list;
lldb::BreakpointSP m_last_created_breakpoint;
@@ -1260,7 +1280,6 @@ protected:
// we can correctly tear down everything that we need to, so the only
// class that knows about the process lifespan is this target class.
lldb::ProcessSP m_process_sp;
bool m_valid;
lldb::SearchFilterSP m_search_filter_sp;
PathMappingList m_image_search_paths;
std::unique_ptr<ClangASTContext> m_scratch_ast_context_ap;
@@ -1273,8 +1292,8 @@ protected:
typedef std::map<lldb::user_id_t, StopHookSP> StopHookCollection;
StopHookCollection m_stop_hooks;
lldb::user_id_t m_stop_hook_next_id;
bool m_valid;
bool m_suppress_stop_hooks;
bool m_suppress_synthetic_value;
static void
ImageSearchPathsChanged (const PathMappingList &path_list,

View File

@@ -181,6 +181,8 @@ class SearchFilter;
class Section;
class SectionImpl;
class SectionList;
class SectionLoadHistory;
class SectionLoadList;
class Settings;
class SourceManager;
class SourceManagerImpl;
@@ -340,6 +342,7 @@ namespace lldb {
#endif // #ifndef LLDB_DISABLE_PYTHON
typedef std::shared_ptr<lldb_private::Section> SectionSP;
typedef std::weak_ptr<lldb_private::Section> SectionWP;
typedef std::shared_ptr<lldb_private::SectionLoadList> SectionLoadListSP;
typedef std::shared_ptr<lldb_private::SearchFilter> SearchFilterSP;
typedef std::shared_ptr<lldb_private::Settings> SettingsSP;
typedef std::shared_ptr<lldb_private::StackFrame> StackFrameSP;

View File

@@ -85,6 +85,8 @@
260E07C8136FAB9200CF21D3 /* OptionGroupFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260E07C7136FAB9200CF21D3 /* OptionGroupFile.cpp */; };
261744781168585B005ADD65 /* SBType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 261744771168585B005ADD65 /* SBType.cpp */; };
2617447A11685869005ADD65 /* SBType.h in Headers */ = {isa = PBXBuildFile; fileRef = 2617447911685869005ADD65 /* SBType.h */; settings = {ATTRIBUTES = (Public, ); }; };
262173A118395D3800C52091 /* SectionLoadHistory.h in Headers */ = {isa = PBXBuildFile; fileRef = 262173A018395D3800C52091 /* SectionLoadHistory.h */; };
262173A318395D4600C52091 /* SectionLoadHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 262173A218395D4600C52091 /* SectionLoadHistory.cpp */; };
26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26274FA514030F79006BA130 /* DynamicLoaderDarwinKernel.cpp */; };
2628A4D513D4977900F5487A /* ThreadKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2628A4D313D4977900F5487A /* ThreadKDP.cpp */; };
262CFC7711A4510000946C6C /* debugserver in Resources */ = {isa = PBXBuildFile; fileRef = 26CE05A0115C31E50022F371 /* debugserver */; };
@@ -952,6 +954,8 @@
2618EE641315B29C001D6D71 /* ThreadGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadGDBRemote.h; sourceTree = "<group>"; };
261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SharingPtr.cpp; path = source/Utility/SharingPtr.cpp; sourceTree = "<group>"; };
261B5A5311C3F2AD00AABD0A /* SharingPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharingPtr.h; path = include/lldb/Utility/SharingPtr.h; sourceTree = "<group>"; };
262173A018395D3800C52091 /* SectionLoadHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SectionLoadHistory.h; path = include/lldb/Target/SectionLoadHistory.h; sourceTree = "<group>"; };
262173A218395D4600C52091 /* SectionLoadHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionLoadHistory.cpp; path = source/Target/SectionLoadHistory.cpp; sourceTree = "<group>"; };
26217930133BC8640083B112 /* lldb-private-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-types.h"; path = "include/lldb/lldb-private-types.h"; sourceTree = "<group>"; };
26217932133BCB850083B112 /* lldb-private-enumerations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-enumerations.h"; path = "include/lldb/lldb-private-enumerations.h"; sourceTree = "<group>"; };
2623096E13D0EFFB006381D9 /* StreamBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StreamBuffer.h; path = include/lldb/Core/StreamBuffer.h; sourceTree = "<group>"; };
@@ -3159,6 +3163,8 @@
26AB54111832DC3400EADFF3 /* RegisterCheckpoint.h */,
26BC7DF410F1B81A00F91463 /* RegisterContext.h */,
26BC7F3710F1B90C00F91463 /* RegisterContext.cpp */,
262173A018395D3800C52091 /* SectionLoadHistory.h */,
262173A218395D4600C52091 /* SectionLoadHistory.cpp */,
2618D78F1240115500F2B8FE /* SectionLoadList.h */,
2618D7911240116900F2B8FE /* SectionLoadList.cpp */,
26BC7DF510F1B81A00F91463 /* StackFrame.h */,
@@ -3688,6 +3694,7 @@
260CC63015D04377002BF2E0 /* OptionValueBoolean.h in Headers */,
260CC63115D04377002BF2E0 /* OptionValueProperties.h in Headers */,
260CC63215D04377002BF2E0 /* OptionValueDictionary.h in Headers */,
262173A118395D3800C52091 /* SectionLoadHistory.h in Headers */,
260CC63315D04377002BF2E0 /* OptionValueEnumeration.h in Headers */,
260CC63415D04377002BF2E0 /* OptionValueFileSpec.h in Headers */,
AF9B8F34182DB52900DA866F /* SystemRuntimeMacOSX.h in Headers */,
@@ -4130,6 +4137,7 @@
2689001A13353DDE00698AC0 /* CommandObjectFrame.cpp in Sources */,
2689001B13353DDE00698AC0 /* CommandObjectHelp.cpp in Sources */,
2689001D13353DDE00698AC0 /* CommandObjectLog.cpp in Sources */,
262173A318395D4600C52091 /* SectionLoadHistory.cpp in Sources */,
2689001E13353DDE00698AC0 /* CommandObjectMemory.cpp in Sources */,
2689001F13353DDE00698AC0 /* CommandObjectPlatform.cpp in Sources */,
2689002013353DDE00698AC0 /* CommandObjectProcess.cpp in Sources */,

View File

@@ -649,6 +649,9 @@ public:
lldb::SBAddress
ResolveLoadAddress (lldb::addr_t vm_addr);
lldb::SBAddress
ResolvePastLoadAddress (uint32_t stop_id, lldb::addr_t vm_addr);
SBSymbolContext
ResolveSymbolContextForAddress (const SBAddress& addr,

View File

@@ -23,6 +23,7 @@
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"

View File

@@ -52,6 +52,7 @@
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
@@ -1263,7 +1264,7 @@ SBTarget::ResolveLoadAddress (lldb::addr_t vm_addr)
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
if (target_sp->GetSectionLoadList().ResolveLoadAddress (vm_addr, addr))
if (target_sp->ResolveLoadAddress (vm_addr, addr))
return sb_addr;
}
@@ -1273,6 +1274,26 @@ SBTarget::ResolveLoadAddress (lldb::addr_t vm_addr)
return sb_addr;
}
lldb::SBAddress
SBTarget::ResolvePastLoadAddress (uint32_t stop_id, lldb::addr_t vm_addr)
{
lldb::SBAddress sb_addr;
Address &addr = sb_addr.ref();
TargetSP target_sp(GetSP());
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
if (target_sp->ResolveLoadAddress (vm_addr, addr))
return sb_addr;
}
// We have a load address that isn't in a section, just return an address
// with the offset filled in (the address) and the section set to NULL
addr.SetRawAddress(vm_addr);
return sb_addr;
}
SBSymbolContext
SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr,
uint32_t resolve_scope)
@@ -2479,10 +2500,14 @@ SBTarget::SetSectionLoadAddress (lldb::SBSection section,
}
else
{
if (target_sp->GetSectionLoadList().SetSectionLoadAddress (section_sp, section_base_addr))
ProcessSP process_sp (target_sp->GetProcessSP());
uint32_t stop_id = 0;
if (process_sp)
stop_id = process_sp->GetStopID();
if (target_sp->SetSectionLoadAddress (section_sp, section_base_addr))
{
// Flush info in the process (stack frames, etc)
ProcessSP process_sp (target_sp->GetProcessSP());
if (process_sp)
process_sp->Flush();
}
@@ -2511,10 +2536,14 @@ SBTarget::ClearSectionLoadAddress (lldb::SBSection section)
}
else
{
if (target_sp->GetSectionLoadList().SetSectionUnloaded (section.GetSP()))
ProcessSP process_sp (target_sp->GetProcessSP());
uint32_t stop_id = 0;
if (process_sp)
stop_id = process_sp->GetStopID();
if (target_sp->SetSectionUnloaded (section.GetSP()))
{
// Flush info in the process (stack frames, etc)
ProcessSP process_sp (target_sp->GetProcessSP());
if (process_sp)
process_sp->Flush();
}
@@ -2586,13 +2615,18 @@ SBTarget::ClearModuleLoadAddress (lldb::SBModule module)
SectionList *section_list = objfile->GetSectionList();
if (section_list)
{
ProcessSP process_sp (target_sp->GetProcessSP());
uint32_t stop_id = 0;
if (process_sp)
stop_id = process_sp->GetStopID();
bool changed = false;
const size_t num_sections = section_list->GetSize();
for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)
{
SectionSP section_sp (section_list->GetSectionAtIndex(sect_idx));
if (section_sp)
changed |= target_sp->GetSectionLoadList().SetSectionUnloaded (section_sp) > 0;
changed |= target_sp->SetSectionUnloaded (section_sp) > 0;
}
if (changed)
{

View File

@@ -19,8 +19,10 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;

View File

@@ -27,6 +27,7 @@
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"

View File

@@ -29,6 +29,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Thread.h"
using namespace lldb;

View File

@@ -28,6 +28,7 @@
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/Options.h"

View File

@@ -49,6 +49,7 @@
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"

View File

@@ -16,6 +16,7 @@
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Symbol/SymbolVendor.h"

View File

@@ -37,6 +37,7 @@
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
using namespace lldb;

View File

@@ -35,6 +35,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"

View File

@@ -33,6 +33,7 @@
#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Symbol/SymbolFile.h"

View File

@@ -10,6 +10,7 @@
#include "lldb/Core/Section.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
using namespace lldb;

View File

@@ -26,6 +26,7 @@
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
using namespace lldb;

View File

@@ -50,6 +50,7 @@
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"

View File

@@ -35,6 +35,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/StackFrame.h"

View File

@@ -921,7 +921,7 @@ DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule (Process *p
const Section *memory_section = memory_section_list->FindSectionByName(ondisk_section_sp->GetName()).get();
if (memory_section)
{
target.GetSectionLoadList().SetSectionLoadAddress (ondisk_section_sp, memory_section->GetFileAddress());
target.SetSectionLoadAddress (ondisk_section_sp, memory_section->GetFileAddress());
++num_sections_loaded;
}
}

View File

@@ -484,13 +484,7 @@ DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo&
// "Section" objects, and "true" for all other sections.
const bool warn_multiple = section_sp->GetName() != g_section_name_LINKEDIT;
const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp);
if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
old_section_load_addr != new_section_load_addr)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp, new_section_load_addr, warn_multiple))
changed = true;
}
changed = m_process->GetTarget().SetSectionLoadAddress (section_sp, new_section_load_addr, warn_multiple);
}
else
{
@@ -568,7 +562,7 @@ DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo&
if (section_sp)
{
const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide;
if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp, old_section_load_addr))
if (m_process->GetTarget().SetSectionUnloaded (section_sp, old_section_load_addr))
changed = true;
}
else
@@ -1524,7 +1518,7 @@ DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process)
DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
Clear(true);
m_process = process;
m_process->GetTarget().GetSectionLoadList().Clear();
m_process->GetTarget().ClearAllLoadedSections();
}
bool
@@ -1541,7 +1535,7 @@ DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint ()
// breakpoint gets hit. We will use this to track when shared
// libraries get loaded/unloaded.
if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr))
if (m_process->GetTarget().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr))
{
Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true, false).get();
dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true);

View File

@@ -211,7 +211,7 @@ DynamicLoaderPOSIXDYLD::CanLoadImage()
void
DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
{
SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
Target &target = m_process->GetTarget();
const SectionList *sections = GetSectionListFromModule(module);
assert(sections && "SectionList missing from loaded module.");
@@ -224,23 +224,20 @@ DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_ad
{
SectionSP section_sp (sections->GetSectionAtIndex(i));
lldb::addr_t new_load_addr = section_sp->GetFileAddress() + base_addr;
lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section_sp);
// If the file address of the section is zero then this is not an
// allocatable/loadable section (property of ELF sh_addr). Skip it.
if (new_load_addr == base_addr)
continue;
if (old_load_addr == LLDB_INVALID_ADDRESS ||
old_load_addr != new_load_addr)
load_list.SetSectionLoadAddress(section_sp, new_load_addr);
target.SetSectionLoadAddress(section_sp, new_load_addr);
}
}
void
DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module)
{
SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
Target &target = m_process->GetTarget();
const SectionList *sections = GetSectionListFromModule(module);
assert(sections && "SectionList missing from unloaded module.");
@@ -251,7 +248,7 @@ DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module)
for (size_t i = 0; i < num_sections; ++i)
{
SectionSP section_sp (sections->GetSectionAtIndex(i));
load_list.SetSectionUnloaded(section_sp);
target.SetSectionUnloaded(section_sp);
}
}

View File

@@ -134,7 +134,7 @@ DynamicLoaderStatic::LoadAllImagesAtFileAddresses ()
SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
if (section_sp)
{
if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress()))
if (m_process->GetTarget().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress()))
changed = true;
}
}

View File

@@ -23,6 +23,7 @@
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"

View File

@@ -26,6 +26,7 @@
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"

View File

@@ -0,0 +1,182 @@
//===-- SectionLoadHistory.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/Target/SectionLoadHistory.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Stream.h"
#include "lldb/Target/SectionLoadList.h"
using namespace lldb;
using namespace lldb_private;
bool
SectionLoadHistory::IsEmpty() const
{
Mutex::Locker locker(m_mutex);
return m_stop_id_to_section_load_list.empty();
}
void
SectionLoadHistory::Clear ()
{
Mutex::Locker locker(m_mutex);
m_stop_id_to_section_load_list.clear();
}
uint32_t
SectionLoadHistory::GetLastStopID() const
{
Mutex::Locker locker(m_mutex);
if (m_stop_id_to_section_load_list.empty())
return 0;
else
return m_stop_id_to_section_load_list.rbegin()->first;
}
SectionLoadList *
SectionLoadHistory::GetSectionLoadListForStopID (uint32_t stop_id, bool read_only)
{
if (m_stop_id_to_section_load_list.empty())
{
SectionLoadListSP section_load_list_sp(new SectionLoadList());
if (stop_id == eStopIDNow)
stop_id = 0;
m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
return section_load_list_sp.get();
}
else
{
if (read_only)
{
// The section load list is for reading data only so we don't need to create
// a new SectionLoadList for the current stop ID, just return the section
// load list for the stop ID that is equal to or less than the current stop ID
if (stop_id == eStopIDNow)
{
// If we are asking for the latest and greatest value, it is always
// at the end of our list becuase that will be the highest stop ID.
StopIDToSectionLoadList::reverse_iterator rpos = m_stop_id_to_section_load_list.rbegin();
return rpos->second.get();
}
else
{
StopIDToSectionLoadList::iterator pos = m_stop_id_to_section_load_list.lower_bound(stop_id);
if (pos != m_stop_id_to_section_load_list.end() && pos->first == stop_id)
return pos->second.get();
else if (pos != m_stop_id_to_section_load_list.begin())
{
--pos;
return pos->second.get();
}
}
}
else
{
// You can only use "eStopIDNow" when reading from the section load history
assert(stop_id != eStopIDNow);
// We are updating the section load list (not read only), so if the stop ID
// passed in isn't the same as the last stop ID in our collection, then create
// a new node using the current stop ID
StopIDToSectionLoadList::iterator pos = m_stop_id_to_section_load_list.lower_bound(stop_id);
if (pos != m_stop_id_to_section_load_list.end() && pos->first == stop_id)
{
// We already have an entry for this value
return pos->second.get();
}
// We must make a new section load list that is based on the last valid
// section load list, so here we copy the last section load list and add
// a new node for the current stop ID.
StopIDToSectionLoadList::reverse_iterator rpos = m_stop_id_to_section_load_list.rbegin();
SectionLoadListSP section_load_list_sp(new SectionLoadList(*rpos->second.get()));
m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
return section_load_list_sp.get();
}
}
return NULL;
}
SectionLoadList &
SectionLoadHistory::GetCurrentSectionLoadList ()
{
const bool read_only = true;
SectionLoadList *section_load_list = GetSectionLoadListForStopID (eStopIDNow, read_only);
assert(section_load_list != NULL);
return *section_load_list;
}
addr_t
SectionLoadHistory::GetSectionLoadAddress (uint32_t stop_id, const lldb::SectionSP &section_sp)
{
Mutex::Locker locker(m_mutex);
const bool read_only = true;
SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
return section_load_list->GetSectionLoadAddress(section_sp);
}
bool
SectionLoadHistory::ResolveLoadAddress (uint32_t stop_id, addr_t load_addr, Address &so_addr)
{
// First find the top level section that this load address exists in
Mutex::Locker locker(m_mutex);
const bool read_only = true;
SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
return section_load_list->ResolveLoadAddress (load_addr, so_addr);
}
bool
SectionLoadHistory::SetSectionLoadAddress (uint32_t stop_id,
const lldb::SectionSP &section_sp,
addr_t load_addr,
bool warn_multiple)
{
Mutex::Locker locker(m_mutex);
const bool read_only = false;
SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
return section_load_list->SetSectionLoadAddress(section_sp, load_addr, warn_multiple);
}
size_t
SectionLoadHistory::SetSectionUnloaded (uint32_t stop_id, const lldb::SectionSP &section_sp)
{
Mutex::Locker locker(m_mutex);
const bool read_only = false;
SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
return section_load_list->SetSectionUnloaded (section_sp);
}
bool
SectionLoadHistory::SetSectionUnloaded (uint32_t stop_id, const lldb::SectionSP &section_sp, addr_t load_addr)
{
Mutex::Locker locker(m_mutex);
const bool read_only = false;
SectionLoadList *section_load_list = GetSectionLoadListForStopID (stop_id, read_only);
return section_load_list->SetSectionUnloaded (section_sp, load_addr);
}
void
SectionLoadHistory::Dump (Stream &s, Target *target)
{
Mutex::Locker locker(m_mutex);
StopIDToSectionLoadList::iterator pos, end = m_stop_id_to_section_load_list.end();
for (pos = m_stop_id_to_section_load_list.begin(); pos != end; ++pos)
{
s.Printf("StopID = %u:\n", pos->first);
pos->second->Dump(s, target);
s.EOL();
}
}

View File

@@ -25,6 +25,25 @@ using namespace lldb;
using namespace lldb_private;
SectionLoadList::SectionLoadList (const SectionLoadList& rhs) :
m_addr_to_sect(),
m_sect_to_addr(),
m_mutex (Mutex::eMutexTypeRecursive)
{
Mutex::Locker locker(rhs.m_mutex);
m_addr_to_sect = rhs.m_addr_to_sect;
m_sect_to_addr = rhs.m_sect_to_addr;
}
void
SectionLoadList::operator=(const SectionLoadList &rhs)
{
Mutex::Locker lhs_locker (m_mutex);
Mutex::Locker rhs_locker (rhs.m_mutex);
m_addr_to_sect = rhs.m_addr_to_sect;
m_sect_to_addr = rhs.m_sect_to_addr;
}
bool
SectionLoadList::IsEmpty() const
{

View File

@@ -42,6 +42,7 @@
#include "lldb/lldb-private-log.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Thread.h"
@@ -69,12 +70,11 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
m_mutex (Mutex::eMutexTypeRecursive),
m_arch (target_arch),
m_images (this),
m_section_load_list (),
m_section_load_history (),
m_breakpoint_list (false),
m_internal_breakpoint_list (true),
m_watchpoint_list (),
m_process_sp (),
m_valid (true),
m_search_filter_sp (),
m_image_search_paths (ImageSearchPathsChanged, this),
m_scratch_ast_context_ap (),
@@ -84,6 +84,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
m_source_manager_ap(),
m_stop_hooks (),
m_stop_hook_next_id (0),
m_valid (true),
m_suppress_stop_hooks (false)
{
SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed");
@@ -158,7 +159,7 @@ Target::DeleteCurrentProcess ()
{
if (m_process_sp.get())
{
m_section_load_list.Clear();
m_section_load_history.Clear();
if (m_process_sp->IsAlive())
m_process_sp->Destroy();
@@ -193,7 +194,7 @@ Target::Destroy()
m_platform_sp.reset();
m_arch.Clear();
ClearModules(true);
m_section_load_list.Clear();
m_section_load_history.Clear();
const bool notify = false;
m_breakpoint_list.RemoveAll(notify);
m_internal_breakpoint_list.RemoveAll(notify);
@@ -314,7 +315,7 @@ Target::CreateBreakpoint (lldb::addr_t addr, bool internal, bool hardware)
// it doesn't resolve to section/offset.
// Try and resolve as a load address if possible
m_section_load_list.ResolveLoadAddress(addr, so_addr);
GetSectionLoadList().ResolveLoadAddress(addr, so_addr);
if (!so_addr.IsValid())
{
// The address didn't resolve, so just set this as an absolute address
@@ -1017,7 +1018,7 @@ void
Target::ClearModules(bool delete_locations)
{
ModulesDidUnload (m_images, delete_locations);
GetSectionLoadList().Clear();
m_section_load_history.Clear();
m_images.Clear();
m_scratch_ast_context_ap.reset();
m_scratch_ast_source_ap.reset();
@@ -1307,7 +1308,8 @@ Target::ReadMemory (const Address& addr,
Address resolved_addr;
if (!addr.IsSectionOffset())
{
if (m_section_load_list.IsEmpty())
SectionLoadList &section_load_list = GetSectionLoadList();
if (section_load_list.IsEmpty())
{
// No sections are loaded, so we must assume we are not running
// yet and anything we are given is a file address.
@@ -1321,7 +1323,7 @@ Target::ReadMemory (const Address& addr,
// or because we have have a live process that has sections loaded
// through the dynamic loader
load_addr = addr.GetOffset(); // "addr" doesn't have a section, so its offset is the load address
m_section_load_list.ResolveLoadAddress (load_addr, resolved_addr);
section_load_list.ResolveLoadAddress (load_addr, resolved_addr);
}
}
if (!resolved_addr.IsValid())
@@ -1534,7 +1536,8 @@ Target::ReadPointerFromMemory (const Address& addr,
addr_t pointer_vm_addr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
if (pointer_vm_addr != LLDB_INVALID_ADDRESS)
{
if (m_section_load_list.IsEmpty())
SectionLoadList &section_load_list = GetSectionLoadList();
if (section_load_list.IsEmpty())
{
// No sections are loaded, so we must assume we are not running
// yet and anything we are given is a file address.
@@ -1546,7 +1549,7 @@ Target::ReadPointerFromMemory (const Address& addr,
// we have manually loaded some sections with "target modules load ..."
// or because we have have a live process that has sections loaded
// through the dynamic loader
m_section_load_list.ResolveLoadAddress (pointer_vm_addr, pointer_addr);
section_load_list.ResolveLoadAddress (pointer_vm_addr, pointer_addr);
}
// We weren't able to resolve the pointer value, so just return
// an address with no section
@@ -2259,6 +2262,61 @@ Target::Install (ProcessLaunchInfo *launch_info)
return error;
}
bool
Target::ResolveLoadAddress (addr_t load_addr, Address &so_addr, uint32_t stop_id)
{
return m_section_load_history.ResolveLoadAddress(stop_id, load_addr, so_addr);
}
bool
Target::SetSectionLoadAddress (const SectionSP &section_sp, addr_t new_section_load_addr, bool warn_multiple)
{
const addr_t old_section_load_addr = m_section_load_history.GetSectionLoadAddress (SectionLoadHistory::eStopIDNow, section_sp);
if (old_section_load_addr != new_section_load_addr)
{
uint32_t stop_id = 0;
ProcessSP process_sp(GetProcessSP());
if (process_sp)
stop_id = process_sp->GetStopID();
else
stop_id = m_section_load_history.GetLastStopID();
if (m_section_load_history.SetSectionLoadAddress (stop_id, section_sp, new_section_load_addr, warn_multiple))
return true; // Return true if the section load address was changed...
}
return false; // Return false to indicate nothing changed
}
bool
Target::SetSectionUnloaded (const lldb::SectionSP &section_sp)
{
uint32_t stop_id = 0;
ProcessSP process_sp(GetProcessSP());
if (process_sp)
stop_id = process_sp->GetStopID();
else
stop_id = m_section_load_history.GetLastStopID();
return m_section_load_history.SetSectionUnloaded (stop_id, section_sp);
}
bool
Target::SetSectionUnloaded (const lldb::SectionSP &section_sp, addr_t load_addr)
{
uint32_t stop_id = 0;
ProcessSP process_sp(GetProcessSP());
if (process_sp)
stop_id = process_sp->GetStopID();
else
stop_id = m_section_load_history.GetLastStopID();
return m_section_load_history.SetSectionUnloaded (stop_id, section_sp, load_addr);
}
void
Target::ClearAllLoadedSections ()
{
m_section_load_history.Clear();
}
//--------------------------------------------------------------
// Target::StopHook
//--------------------------------------------------------------

View File

@@ -28,6 +28,7 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
using namespace lldb;