<rdar://problem/13892516>
LLDB can now debug across calls to exec when the architecture changes from say i386 to x86_64 (on darwin). llvm-svn: 182345
This commit is contained in:
parent
9d4c735885
commit
15fc2be75b
|
@ -38,7 +38,7 @@ namespace lldb_private {
|
|||
~MemoryCache ();
|
||||
|
||||
void
|
||||
Clear();
|
||||
Clear(bool clear_invalid_ranges = false);
|
||||
|
||||
void
|
||||
Flush (lldb::addr_t addr, size_t size);
|
||||
|
|
|
@ -1011,7 +1011,6 @@ ProcessGDBRemote::DoDidExec ()
|
|||
// The process exec'ed itself, figure out the dynamic loader, etc...
|
||||
BuildDynamicRegisterInfo (true);
|
||||
m_gdb_comm.ResetDiscoverableSettings();
|
||||
DidLaunchOrAttach ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1350,7 +1349,20 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
|
|||
case 'T':
|
||||
case 'S':
|
||||
{
|
||||
if (GetStopID() == 0)
|
||||
// This is a bit of a hack, but is is required. If we did exec, we
|
||||
// need to clear our thread lists and also know to rebuild our dynamic
|
||||
// register info before we lookup and threads and populate the expedited
|
||||
// register values so we need to know this right away so we can cleanup
|
||||
// and update our registers.
|
||||
const bool did_exec = stop_packet.GetStringRef().find(";reason:exec;") != std::string::npos;
|
||||
|
||||
if (did_exec)
|
||||
{
|
||||
m_thread_list_real.Clear();
|
||||
m_thread_list.Clear();
|
||||
}
|
||||
|
||||
if (GetStopID() == 0 || did_exec)
|
||||
{
|
||||
// Our first stop, make sure we have a process ID, and also make
|
||||
// sure we know about our registers
|
||||
|
@ -1552,9 +1564,14 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
|
|||
thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
|
||||
handled = true;
|
||||
}
|
||||
else if (reason.compare("exec") == 0)
|
||||
{
|
||||
thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (signo)
|
||||
if (signo && did_exec == false)
|
||||
{
|
||||
if (signo == SIGTRAP)
|
||||
{
|
||||
|
|
|
@ -40,10 +40,12 @@ MemoryCache::~MemoryCache()
|
|||
}
|
||||
|
||||
void
|
||||
MemoryCache::Clear()
|
||||
MemoryCache::Clear(bool clear_invalid_ranges)
|
||||
{
|
||||
Mutex::Locker locker (m_mutex);
|
||||
m_cache.clear();
|
||||
if (clear_invalid_ranges)
|
||||
m_invalid_ranges.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -5587,6 +5587,10 @@ Process::DidExec ()
|
|||
m_image_tokens.clear();
|
||||
m_allocated_memory_cache.Clear();
|
||||
m_language_runtimes.clear();
|
||||
m_thread_list.DiscardThreadPlans();
|
||||
m_thread_list.Clear();
|
||||
m_thread_list_real.Clear();
|
||||
m_memory_cache.Clear(true);
|
||||
DoDidExec();
|
||||
CompleteAttach ();
|
||||
}
|
||||
|
|
|
@ -97,8 +97,6 @@
|
|||
26C637E80C71334A0024798E /* dbgnub-mig.defs */ = {isa = PBXFileReference; explicitFileType = sourcecode.mig; fileEncoding = 30; path = "dbgnub-mig.defs"; sourceTree = "<group>"; };
|
||||
26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImplI386.cpp; sourceTree = "<group>"; };
|
||||
26C637EB0C71334A0024798E /* DNBArchImplI386.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBArchImplI386.h; sourceTree = "<group>"; };
|
||||
26C637EC0C71334A0024798E /* MachDYLD.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachDYLD.cpp; sourceTree = "<group>"; };
|
||||
26C637ED0C71334A0024798E /* MachDYLD.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachDYLD.h; sourceTree = "<group>"; };
|
||||
26C637EE0C71334A0024798E /* MachException.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachException.cpp; sourceTree = "<group>"; };
|
||||
26C637EF0C71334A0024798E /* MachException.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachException.h; sourceTree = "<group>"; };
|
||||
26C637F00C71334A0024798E /* MachProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachProcess.cpp; sourceTree = "<group>"; };
|
||||
|
@ -277,8 +275,6 @@
|
|||
4971AE7013D10F4F00649E37 /* HasAVX.h */,
|
||||
4971AE7113D10F4F00649E37 /* HasAVX.s */,
|
||||
26C637E80C71334A0024798E /* dbgnub-mig.defs */,
|
||||
26C637ED0C71334A0024798E /* MachDYLD.h */,
|
||||
26C637EC0C71334A0024798E /* MachDYLD.cpp */,
|
||||
26C637EF0C71334A0024798E /* MachException.h */,
|
||||
26C637EE0C71334A0024798E /* MachException.cpp */,
|
||||
26C637F10C71334A0024798E /* MachProcess.h */,
|
||||
|
|
|
@ -288,6 +288,15 @@ DNBBreakpointList::GetByIndex (uint32_t i)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
DNBBreakpointList::DisableAll ()
|
||||
{
|
||||
iterator pos, end = m_breakpoints.end();
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
(*pos).SetEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
const DNBBreakpoint *
|
||||
DNBBreakpointList::GetByIndex (uint32_t i) const
|
||||
{
|
||||
|
|
|
@ -145,6 +145,7 @@ public:
|
|||
size_t Size() const { return m_breakpoints.size(); }
|
||||
DNBBreakpoint * GetByIndex (uint32_t i);
|
||||
const DNBBreakpoint * GetByIndex (uint32_t i) const;
|
||||
void DisableAll ();
|
||||
|
||||
protected:
|
||||
typedef std::list<DNBBreakpoint> collection;
|
||||
|
|
|
@ -237,7 +237,8 @@ enum DNBThreadStopType
|
|||
{
|
||||
eStopTypeInvalid = 0,
|
||||
eStopTypeSignal,
|
||||
eStopTypeException
|
||||
eStopTypeException,
|
||||
eStopTypeExec
|
||||
};
|
||||
|
||||
enum DNBMemoryPermissions
|
||||
|
|
|
@ -1,679 +0,0 @@
|
|||
//===-- MachDYLD.cpp --------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Created by Greg Clayton on 6/29/07.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MachDYLD.h"
|
||||
#include "DNB.h"
|
||||
#include "DNBDataRef.h"
|
||||
#include <mach-o/loader.h>
|
||||
#include "DNBLog.h"
|
||||
|
||||
MachDYLD::MachDYLD() :
|
||||
m_pid(INVALID_NUB_PROCESS),
|
||||
m_addr_size(4),
|
||||
m_dyld_addr(INVALID_NUB_ADDRESS),
|
||||
m_dyld_all_image_infos_addr(INVALID_NUB_ADDRESS),
|
||||
m_dylib_info_header(),
|
||||
m_current_dylibs(),
|
||||
m_changed_dylibs(),
|
||||
m_notify_break_id(INVALID_NUB_BREAK_ID),
|
||||
m_dyld_info_mutex(PTHREAD_MUTEX_RECURSIVE)
|
||||
{
|
||||
}
|
||||
|
||||
MachDYLD::~MachDYLD()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MachDYLD::Clear()
|
||||
{
|
||||
PThreadMutex::Locker locker(m_dyld_info_mutex);
|
||||
|
||||
nub_process_t pid = m_pid;
|
||||
if (pid != INVALID_NUB_PROCESS)
|
||||
{
|
||||
DNBProcessSetSharedLibraryInfoCallback ( pid, NULL, NULL);
|
||||
DNBBreakpointClear(pid, m_notify_break_id);
|
||||
}
|
||||
|
||||
m_addr_size = 4;
|
||||
m_dyld_addr = INVALID_NUB_ADDRESS;
|
||||
m_dyld_all_image_infos_addr = INVALID_NUB_ADDRESS;
|
||||
m_dylib_info_header.Clear();
|
||||
m_current_dylibs.clear();
|
||||
m_changed_dylibs.clear();
|
||||
m_notify_break_id = INVALID_NUB_BREAK_ID;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MachDYLD::Initialize(nub_process_t pid)
|
||||
{
|
||||
//printf("MachDYLD::%s(0x%4.4x)\n", __FUNCTION__, pid);
|
||||
Clear();
|
||||
m_pid = pid;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MachDYLD::ProcessStateChanged(nub_state_t state)
|
||||
{
|
||||
//printf("MachDYLD::%s(%s)\n", __FUNCTION__, DNBStateAsString(state));
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case eStateInvalid:
|
||||
case eStateUnloaded:
|
||||
case eStateExited:
|
||||
case eStateDetached:
|
||||
case eStateAttaching:
|
||||
case eStateLaunching:
|
||||
Clear();
|
||||
break;
|
||||
|
||||
case eStateStopped:
|
||||
// Keep trying find dyld each time we stop until we do
|
||||
if (!FoundDYLD())
|
||||
{
|
||||
assert(m_pid != INVALID_NUB_PROCESS);
|
||||
DNBProcessSetSharedLibraryInfoCallback ( m_pid, CopySharedInfoCallback, this);
|
||||
CheckForDYLDInMemory();
|
||||
}
|
||||
break;
|
||||
|
||||
case eStateRunning:
|
||||
case eStateStepping:
|
||||
case eStateCrashed:
|
||||
case eStateSuspended:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MachDYLD::SharedLibraryStateChanged(DNBExecutableImageInfo *image_infos, nub_size_t num_image_infos)
|
||||
{
|
||||
//printf("MachDYLD::%s(%p, %u)\n", __FUNCTION__, image_infos, image_infos);
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
MachDYLD::FoundDYLD() const
|
||||
{
|
||||
return m_dyld_addr != INVALID_NUB_ADDRESS;
|
||||
}
|
||||
|
||||
bool
|
||||
MachDYLD::CheckForDYLDInMemory()
|
||||
{
|
||||
#if defined (__arm__)
|
||||
return CheckForDYLDInMemory(0x2fe00000);
|
||||
#else
|
||||
return CheckForDYLDInMemory(0x8fe00000);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
MachDYLD::CheckForDYLDInMemory(nub_addr_t addr)
|
||||
{
|
||||
std::vector<uint8_t> dyld_header;
|
||||
nub_size_t page_size = 0x1000;
|
||||
dyld_header.resize(page_size);
|
||||
nub_size_t bytes_read = DNBProcessMemoryRead(m_pid, addr, dyld_header.size(), &dyld_header[0]);
|
||||
if (bytes_read > 0)
|
||||
{
|
||||
DNBDataRef::offset_t offset = 0;
|
||||
DNBDataRef data(&dyld_header[0], bytes_read, false);
|
||||
struct mach_header *header = (struct mach_header*)data.GetData(&offset, sizeof(struct mach_header));
|
||||
if (header)
|
||||
{
|
||||
switch (header->magic)
|
||||
{
|
||||
case MH_MAGIC:
|
||||
case MH_CIGAM:
|
||||
data.SetPointerSize(4);
|
||||
m_addr_size = 4;
|
||||
break;
|
||||
|
||||
case MH_MAGIC_64:
|
||||
case MH_CIGAM_64:
|
||||
data.SetPointerSize(8);
|
||||
m_addr_size = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header->filetype == MH_DYLINKER)
|
||||
{
|
||||
// printf( "Found DYLD mach image at %8.8p", addr);
|
||||
|
||||
m_dyld_all_image_infos_addr = DNBProcessLookupAddress(m_pid, "dyld_all_image_infos", "/usr/lib/dyld");
|
||||
|
||||
#if defined (__arm__)
|
||||
m_dyld_all_image_infos_addr = 0x2fe3a004;
|
||||
#endif
|
||||
|
||||
if (m_dyld_all_image_infos_addr != INVALID_NUB_ADDRESS)
|
||||
{
|
||||
// printf( "Found DYLD data symbol 'dyld_all_image_infos' is %8.8p", m_dyld_all_image_infos_addr);
|
||||
|
||||
if (ReadDYLIBInfo())
|
||||
{
|
||||
if (m_dylib_info_header.notification != INVALID_NUB_ADDRESS)
|
||||
{
|
||||
m_notify_break_id = DNBBreakpointSet(m_pid, m_dylib_info_header.notification, 4, true);
|
||||
if (NUB_BREAK_ID_IS_VALID(m_notify_break_id))
|
||||
{
|
||||
DNBBreakpointSetCallback(m_pid, m_notify_break_id, MachDYLD::BreakpointHit, this);
|
||||
m_dyld_addr = addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (DNBLogCheckLogBit(LOG_SHLIB))
|
||||
// Dump(DNBLogGetLogFile());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nub_bool_t
|
||||
MachDYLD::BreakpointHit(nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton)
|
||||
{
|
||||
MachDYLD *dyld = (MachDYLD*) baton;
|
||||
//printf("MachDYLD::BreakpointHit called");
|
||||
dyld->ReadDYLIBInfo();
|
||||
DNBProcessSharedLibrariesUpdated(pid);
|
||||
return false; // Don't stop the process, let it continue
|
||||
}
|
||||
|
||||
bool
|
||||
MachDYLD::ReadDYLIBInfo()
|
||||
{
|
||||
nub_addr_t addr = m_dyld_all_image_infos_addr;
|
||||
if (addr != INVALID_NUB_ADDRESS)
|
||||
{
|
||||
PThreadMutex::Locker locker(m_dyld_info_mutex);
|
||||
//printf("MachDYLD::ReadDYLIBInfo(addr =%8.8p)", addr);
|
||||
bool swap = false;
|
||||
uint32_t i = 0;
|
||||
DYLIBInfo::collection previous_dylibs;
|
||||
previous_dylibs.swap(m_current_dylibs);
|
||||
uint8_t all_dylib_info_data[32];
|
||||
nub_size_t count = 8 + m_addr_size * 2;
|
||||
nub_size_t bytes_read = DNBProcessMemoryRead(m_pid, addr, count, &all_dylib_info_data[0]);
|
||||
if (bytes_read != count)
|
||||
{
|
||||
m_dylib_info_header.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
DNBDataRef data(all_dylib_info_data, sizeof(all_dylib_info_data), swap);
|
||||
data.SetPointerSize(m_addr_size);
|
||||
DNBDataRef::offset_t offset = 0;
|
||||
m_dylib_info_header.version = data.Get32(&offset);
|
||||
m_dylib_info_header.dylib_info_count = data.Get32(&offset);
|
||||
m_dylib_info_header.dylib_info_addr = data.GetPointer(&offset);
|
||||
m_dylib_info_header.notification = data.GetPointer(&offset);
|
||||
//printf( "%s: version=%d, count=%d, addr=%8.8p, notify=%8.8p",
|
||||
// __PRETTY_FUNCTION__,
|
||||
// m_dylib_info_header.version,
|
||||
// m_dylib_info_header.dylib_info_count,
|
||||
// m_dylib_info_header.dylib_info_addr,
|
||||
// m_dylib_info_header.notification);
|
||||
|
||||
switch (m_dylib_info_header.version)
|
||||
{
|
||||
case 1: // 10.4.x and prior
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // 10.5 and later
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//printf( "Invalid dyld all_dylib_infos version number: %d", m_dylib_info_header.version);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// If we made it here, we are assuming that the all dylib info data should
|
||||
// be valid, lets read the info array.
|
||||
if (m_dylib_info_header.dylib_info_count > 0)
|
||||
{
|
||||
if (m_dylib_info_header.dylib_info_addr == 0)
|
||||
{
|
||||
//printf( "dyld is currently updating all_dylib_infos.");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_current_dylibs.resize(m_dylib_info_header.dylib_info_count);
|
||||
count = m_current_dylibs.size() * 3 * m_addr_size;
|
||||
std::vector<uint8_t> info_data(count, 0);
|
||||
bytes_read = DNBProcessMemoryRead(m_pid, m_dylib_info_header.dylib_info_addr, count, &info_data[0]);
|
||||
if (bytes_read == count)
|
||||
{
|
||||
DNBDataRef::offset_t info_data_offset = 0;
|
||||
DNBDataRef info_data_ref(&info_data[0], info_data.size(), swap);
|
||||
info_data_ref.SetPointerSize(m_addr_size);
|
||||
for (i = 0; info_data_ref.ValidOffset(info_data_offset); i++)
|
||||
{
|
||||
assert (i < m_current_dylibs.size());
|
||||
m_current_dylibs[i].address = info_data_ref.GetPointer(&info_data_offset);
|
||||
nub_addr_t path_addr = info_data_ref.GetPointer(&info_data_offset);
|
||||
m_current_dylibs[i].mod_date = info_data_ref.GetPointer(&info_data_offset);
|
||||
|
||||
char raw_path[PATH_MAX];
|
||||
char resolved_path[PATH_MAX];
|
||||
bytes_read = DNBProcessMemoryRead(m_pid, path_addr, sizeof(raw_path), (char*)&raw_path[0]);
|
||||
if (::realpath(raw_path, resolved_path))
|
||||
m_current_dylibs[i].path = resolved_path;
|
||||
else
|
||||
m_current_dylibs[i].path = raw_path;
|
||||
}
|
||||
assert(i == m_dylib_info_header.dylib_info_count);
|
||||
|
||||
UpdateUUIDs();
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf( "unable to read all data for all_dylib_infos.");
|
||||
m_current_dylibs.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Read any UUID values that we can get
|
||||
if (m_current_dylibs.empty())
|
||||
{
|
||||
m_changed_dylibs = previous_dylibs;
|
||||
const size_t num_changed_dylibs = m_changed_dylibs.size();
|
||||
for (i = 0; i < num_changed_dylibs; i++)
|
||||
{
|
||||
// Indicate the shared library was unloaded by giving it an invalid
|
||||
// address...
|
||||
m_changed_dylibs[i].address = INVALID_NUB_ADDRESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_changed_dylibs.clear();
|
||||
|
||||
// Most of the time when we get shared library changes, they just
|
||||
// get appended to the end of the list, so find out the min number
|
||||
// of entries in the current and previous list that match and see
|
||||
// how many are equal.
|
||||
uint32_t curr_dylib_count = m_current_dylibs.size();
|
||||
uint32_t prev_dylib_count = previous_dylibs.size();
|
||||
uint32_t common_count = std::min<uint32_t>(prev_dylib_count, curr_dylib_count);
|
||||
MachDYLD::DYLIBInfo::const_iterator curr_pos = m_current_dylibs.begin();
|
||||
MachDYLD::DYLIBInfo::const_iterator curr_end = m_current_dylibs.end();
|
||||
MachDYLD::DYLIBInfo::iterator prev_pos = previous_dylibs.begin();
|
||||
uint32_t idx;
|
||||
for (idx = 0; idx < common_count; idx++)
|
||||
{
|
||||
if (*curr_pos == *prev_pos)
|
||||
{
|
||||
++curr_pos;
|
||||
++prev_pos;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove all the entries that were at the exact same index and that
|
||||
// matched between the previous_dylibs and m_current_dylibs arrays. This will cover
|
||||
// most of the cases as when shared libraries get loaded they get
|
||||
// appended to the end of the list.
|
||||
if (prev_pos != previous_dylibs.begin())
|
||||
{
|
||||
previous_dylibs.erase(previous_dylibs.begin(), prev_pos);
|
||||
}
|
||||
|
||||
if (previous_dylibs.empty())
|
||||
{
|
||||
// We only have new libraries to add, they are the only ones that
|
||||
// have changed.
|
||||
if (curr_pos != curr_end)
|
||||
{
|
||||
m_changed_dylibs.assign(curr_pos, curr_end);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We still have items in our previous dylib list which means either
|
||||
// one or more shared libraries got unloaded somewhere in the middle
|
||||
// of the list, so we will manually search for each remaining item
|
||||
// in our current list in the previous list
|
||||
for (; curr_pos != curr_end; ++curr_pos)
|
||||
{
|
||||
MachDYLD::DYLIBInfo::iterator pos = std::find(previous_dylibs.begin(), previous_dylibs.end(), *curr_pos);
|
||||
if (pos == previous_dylibs.end())
|
||||
{
|
||||
// This dylib wasn't here before, add it to our change list
|
||||
m_changed_dylibs.push_back(*curr_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This dylib was in our previous dylib list, it didn't
|
||||
// change, so lets remove it from the previous list so we
|
||||
// don't see it again.
|
||||
previous_dylibs.erase(pos);
|
||||
}
|
||||
}
|
||||
|
||||
// The only items left if our previous_dylibs array will be shared
|
||||
// libraries that got unloaded (still in previous list, and not
|
||||
// mentioned in the current list).
|
||||
if (!previous_dylibs.empty())
|
||||
{
|
||||
const size_t num_previous_dylibs = previous_dylibs.size();
|
||||
for (i = 0; i < num_previous_dylibs; i++)
|
||||
{
|
||||
// Indicate the shared library was unloaded by giving it
|
||||
// an invalid address...
|
||||
previous_dylibs[i].address = INVALID_NUB_ADDRESS;
|
||||
}
|
||||
// Add all remaining previous_dylibs to the changed list with
|
||||
// invalidated addresses so we know they got unloaded.
|
||||
m_changed_dylibs.insert(m_changed_dylibs.end(), previous_dylibs.begin(), previous_dylibs.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MachDYLD::UpdateUUIDs()
|
||||
{
|
||||
bool swap = false;
|
||||
nub_size_t page_size = 0x1000;
|
||||
uint32_t i;
|
||||
// Read any UUID values that we can get
|
||||
for (i = 0; i < m_dylib_info_header.dylib_info_count; i++)
|
||||
{
|
||||
if (!m_current_dylibs[i].UUIDValid())
|
||||
{
|
||||
std::vector<uint8_t> bytes(page_size, 0);
|
||||
nub_size_t bytes_read = DNBProcessMemoryRead(m_pid, m_current_dylibs[i].address, page_size, &bytes[0]);
|
||||
if (bytes_read > 0)
|
||||
{
|
||||
DNBDataRef::offset_t offset = 0;
|
||||
DNBDataRef data(&bytes[0], bytes_read, swap);
|
||||
struct mach_header *header = (struct mach_header*)data.GetData(&offset, sizeof(struct mach_header));
|
||||
if (header)
|
||||
{
|
||||
switch (header->magic)
|
||||
{
|
||||
case MH_MAGIC:
|
||||
case MH_CIGAM:
|
||||
data.SetPointerSize(4);
|
||||
m_addr_size = 4;
|
||||
break;
|
||||
|
||||
case MH_MAGIC_64:
|
||||
case MH_CIGAM_64:
|
||||
data.SetPointerSize(8);
|
||||
m_addr_size = 8;
|
||||
offset += 4; // Skip the extra reserved field in the 64 bit mach header
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (header->sizeofcmds > bytes_read)
|
||||
{
|
||||
bytes.resize(header->sizeofcmds);
|
||||
nub_addr_t addr = m_current_dylibs[i].address + bytes_read;
|
||||
bytes_read += DNBProcessMemoryRead(m_pid, addr , header->sizeofcmds - bytes_read, &bytes[bytes_read]);
|
||||
}
|
||||
assert(bytes_read >= header->sizeofcmds);
|
||||
uint32_t cmd_idx;
|
||||
DNBSegment segment;
|
||||
|
||||
for (cmd_idx = 0; cmd_idx < header->ncmds; cmd_idx++)
|
||||
{
|
||||
if (data.ValidOffsetForDataOfSize(offset, sizeof(struct load_command)))
|
||||
{
|
||||
struct load_command load_cmd;
|
||||
DNBDataRef::offset_t load_cmd_offset = offset;
|
||||
load_cmd.cmd = data.Get32(&offset);
|
||||
load_cmd.cmdsize = data.Get32(&offset);
|
||||
switch (load_cmd.cmd)
|
||||
{
|
||||
case LC_SEGMENT:
|
||||
{
|
||||
strncpy(segment.name, data.GetCStr(&offset, 16), 16);
|
||||
memset(&segment.name[16], 0, DNB_MAX_SEGMENT_NAME_LENGTH - 16);
|
||||
segment.addr = data.Get32(&offset);
|
||||
segment.size = data.Get32(&offset);
|
||||
m_current_dylibs[i].segments.push_back(segment);
|
||||
}
|
||||
break;
|
||||
|
||||
case LC_SEGMENT_64:
|
||||
{
|
||||
strncpy(segment.name, data.GetCStr(&offset, 16), 16);
|
||||
memset(&segment.name[16], 0, DNB_MAX_SEGMENT_NAME_LENGTH - 16);
|
||||
segment.addr = data.Get64(&offset);
|
||||
segment.size = data.Get64(&offset);
|
||||
m_current_dylibs[i].segments.push_back(segment);
|
||||
}
|
||||
break;
|
||||
|
||||
case LC_UUID:
|
||||
// We found our UUID, we can stop now...
|
||||
memcpy(m_current_dylibs[i].uuid, data.GetData(&offset, 16), 16);
|
||||
// if (DNBLogCheckLogBit(LOG_SHLIB))
|
||||
// {
|
||||
// DNBLogThreaded("UUID found for aii[%d]:", i);
|
||||
// m_current_dylibs[i].Dump(DNBLogGetLogFile());
|
||||
// }
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Set offset to be the beginning of the next load command.
|
||||
offset = load_cmd_offset + load_cmd.cmdsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nub_addr_t
|
||||
MachDYLD::GetSharedLibraryHeaderAddress(const char *shlib_path) const
|
||||
{
|
||||
if (!m_current_dylibs.empty() && shlib_path && shlib_path[0])
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i<m_current_dylibs.size(); i++)
|
||||
{
|
||||
if (m_current_dylibs[i].path == shlib_path)
|
||||
return m_current_dylibs[i].address;
|
||||
}
|
||||
}
|
||||
return INVALID_NUB_ADDRESS;
|
||||
}
|
||||
|
||||
|
||||
nub_size_t
|
||||
MachDYLD::CopySharedLibraryInfo(DYLIBInfo::collection& dylib_coll, DNBExecutableImageInfo **image_infos)
|
||||
{
|
||||
if (!dylib_coll.empty())
|
||||
{
|
||||
size_t i;
|
||||
size_t total_num_segments = 0;
|
||||
size_t segment_index = 0;
|
||||
for (i = 0; i<dylib_coll.size(); i++)
|
||||
{
|
||||
total_num_segments += dylib_coll[i].segments.size();
|
||||
}
|
||||
size_t image_infos_byte_size = sizeof(DNBExecutableImageInfo) * dylib_coll.size();
|
||||
size_t all_segments_byte_size = sizeof(DNBSegment) * total_num_segments;
|
||||
size_t total_byte_size = image_infos_byte_size + all_segments_byte_size;
|
||||
|
||||
// Allocate enough space to fit all of the shared library information in
|
||||
// a single buffer so consumers can free a single chunk of data when done
|
||||
uint8_t *buf = (uint8_t*)malloc (total_byte_size);
|
||||
|
||||
DNBExecutableImageInfo *info = (DNBExecutableImageInfo*)buf;
|
||||
DNBSegment *all_segments = (DNBSegment*)(buf + image_infos_byte_size);
|
||||
if (info)
|
||||
{
|
||||
for (i = 0; i<dylib_coll.size(); i++)
|
||||
{
|
||||
strncpy(info[i].name, dylib_coll[i].path.c_str(), PATH_MAX);
|
||||
// NULL terminate paths that are too long (redundant for path
|
||||
// that fit, but harmless
|
||||
info[i].name[PATH_MAX-1] = '\0';
|
||||
info[i].header_addr = dylib_coll[i].address;
|
||||
info[i].state = (dylib_coll[i].address == INVALID_NUB_ADDRESS ? eShlibStateUnloaded : eShlibStateLoaded);
|
||||
memcpy(info[i].uuid, dylib_coll[i].uuid, sizeof(uuid_t));
|
||||
info[i].num_segments = dylib_coll[i].segments.size();
|
||||
if (info[i].num_segments == 0)
|
||||
{
|
||||
info[i].segments = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
info[i].segments = &all_segments[segment_index];
|
||||
memcpy(info[i].segments, &(dylib_coll[i].segments[0]), sizeof(DNBSegment) * info[i].num_segments);
|
||||
segment_index += info[i].num_segments;
|
||||
}
|
||||
|
||||
}
|
||||
// Release ownership of the shared library array to the caller
|
||||
*image_infos = info;
|
||||
return dylib_coll.size();
|
||||
}
|
||||
}
|
||||
*image_infos = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nub_size_t
|
||||
MachDYLD::CopySharedInfoCallback(nub_process_t pid, struct DNBExecutableImageInfo **image_infos, nub_bool_t only_changed, void *baton)
|
||||
{
|
||||
MachDYLD *dyld = (MachDYLD*) baton;
|
||||
|
||||
if (only_changed)
|
||||
return dyld->CopyChangedShlibInfo(image_infos);
|
||||
else
|
||||
return dyld->CopyCurrentShlibInfo(image_infos);
|
||||
|
||||
*image_infos = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nub_size_t
|
||||
MachDYLD::CopyCurrentShlibInfo(DNBExecutableImageInfo **image_infos)
|
||||
{
|
||||
PThreadMutex::Locker locker(m_dyld_info_mutex);
|
||||
return CopySharedLibraryInfo(m_current_dylibs, image_infos);
|
||||
}
|
||||
|
||||
|
||||
nub_size_t
|
||||
MachDYLD::CopyChangedShlibInfo(DNBExecutableImageInfo **image_infos)
|
||||
{
|
||||
PThreadMutex::Locker locker(m_dyld_info_mutex);
|
||||
return CopySharedLibraryInfo(m_changed_dylibs, image_infos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
MachDYLD::DYLIBInfo::Dump(FILE *f) const
|
||||
{
|
||||
if (f == NULL)
|
||||
return;
|
||||
if (address == INVALID_NUB_ADDRESS)
|
||||
{
|
||||
if (UUIDValid())
|
||||
{
|
||||
fprintf(f, "UNLOADED %8.8llx %2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X %s",
|
||||
(uint64_t)mod_date,
|
||||
uuid[ 0], uuid[ 1], uuid[ 2], uuid[ 3],
|
||||
uuid[ 4], uuid[ 5], uuid[ 6], uuid[ 7],
|
||||
uuid[ 8], uuid[ 9], uuid[10], uuid[11],
|
||||
uuid[12], uuid[13], uuid[14], uuid[15],
|
||||
path.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(f, "UNLOADED %8.8llx %s", (uint64_t)mod_date, path.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (UUIDValid())
|
||||
{
|
||||
fprintf(f, "%8.8llx %8.8llx %2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X %s",
|
||||
(uint64_t)address,
|
||||
(uint64_t)mod_date,
|
||||
uuid[ 0], uuid[ 1], uuid[ 2], uuid[ 3],
|
||||
uuid[ 4], uuid[ 5], uuid[ 6], uuid[ 7],
|
||||
uuid[ 8], uuid[ 9], uuid[10], uuid[11],
|
||||
uuid[12], uuid[13], uuid[14], uuid[15],
|
||||
path.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(f, "%8.8llx %8.8llx %s", (uint64_t)address, (uint64_t)mod_date, path.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MachDYLD::Dump(FILE *f) const
|
||||
{
|
||||
if (f == NULL)
|
||||
return;
|
||||
|
||||
PThreadMutex::Locker locker(m_dyld_info_mutex);
|
||||
fprintf(f, "\n\tMachDYLD.m_dylib_info_header: version=%d, count=%d, addr=0x%llx, notify=0x%llx",
|
||||
m_dylib_info_header.version,
|
||||
m_dylib_info_header.dylib_info_count,
|
||||
(uint64_t)m_dylib_info_header.dylib_info_addr,
|
||||
(uint64_t)m_dylib_info_header.notification);
|
||||
uint32_t i;
|
||||
fprintf(f, "\n\tMachDYLD.m_current_dylibs");
|
||||
for (i = 0; i<m_current_dylibs.size(); i++)
|
||||
m_current_dylibs[i].Dump(f);
|
||||
fprintf(f, "\n\tMachDYLD.m_changed_dylibs");
|
||||
for (i = 0; i<m_changed_dylibs.size(); i++)
|
||||
m_changed_dylibs[i].Dump(f);
|
||||
}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
//===-- MachDYLD.h ----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Created by Greg Clayton on 6/29/07.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __MachDYLD_h__
|
||||
#define __MachDYLD_h__
|
||||
|
||||
#include "DNBDefs.h"
|
||||
#include "DNBRuntimeAction.h"
|
||||
#include "PThreadMutex.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class DNBBreakpoint;
|
||||
class MachProcess;
|
||||
|
||||
class MachDYLD : public DNBRuntimeAction
|
||||
{
|
||||
public:
|
||||
MachDYLD ();
|
||||
virtual ~MachDYLD ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// DNBRuntimeAction required functions
|
||||
//------------------------------------------------------------------
|
||||
virtual void Initialize(nub_process_t pid);
|
||||
virtual void ProcessStateChanged(nub_state_t state);
|
||||
virtual void SharedLibraryStateChanged(DNBExecutableImageInfo *image_infos, nub_size_t num_image_infos);
|
||||
|
||||
protected:
|
||||
bool CheckForDYLDInMemory();
|
||||
bool FoundDYLD() const;
|
||||
void Clear();
|
||||
void Dump(FILE *f) const;
|
||||
nub_process_t ProcessID() const { return m_pid; }
|
||||
uint32_t AddrByteSize() const { return m_addr_size; }
|
||||
nub_size_t CopyCurrentShlibInfo(DNBExecutableImageInfo **image_infos);
|
||||
nub_size_t CopyChangedShlibInfo(DNBExecutableImageInfo **image_infos);
|
||||
nub_addr_t GetSharedLibraryHeaderAddress(const char *shlib_path) const;
|
||||
bool CheckForDYLDInMemory(nub_addr_t addr);
|
||||
bool ReadDYLIBInfo ();
|
||||
static nub_bool_t BreakpointHit (nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton);
|
||||
void UpdateUUIDs();
|
||||
|
||||
struct DYLIBInfo
|
||||
{
|
||||
nub_addr_t address; // Address of mach header for this dylib
|
||||
nub_addr_t mod_date; // Modification date for this dylib
|
||||
std::string path; // Resolved path for this dylib
|
||||
uint8_t uuid[16]; // UUID for this dylib if it has one, else all zeros
|
||||
std::vector<DNBSegment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
|
||||
|
||||
DYLIBInfo() :
|
||||
address(INVALID_NUB_ADDRESS),
|
||||
mod_date(0),
|
||||
path(),
|
||||
segments()
|
||||
{
|
||||
memset(uuid, 0, 16);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
address = INVALID_NUB_ADDRESS;
|
||||
mod_date = 0;
|
||||
path.clear();
|
||||
segments.clear();
|
||||
memset(uuid, 0, 16);
|
||||
}
|
||||
|
||||
bool operator == (const DYLIBInfo& rhs) const
|
||||
{
|
||||
return address == rhs.address
|
||||
&& mod_date == rhs.mod_date
|
||||
&& path == rhs.path
|
||||
&& memcmp(uuid, rhs.uuid, 16) == 0;
|
||||
}
|
||||
bool UUIDValid() const
|
||||
{
|
||||
return uuid[ 0] || uuid[ 1] || uuid[ 2] || uuid[ 3] ||
|
||||
uuid[ 4] || uuid[ 5] || uuid[ 6] || uuid[ 7] ||
|
||||
uuid[ 8] || uuid[ 9] || uuid[10] || uuid[11] ||
|
||||
uuid[12] || uuid[13] || uuid[14] || uuid[15];
|
||||
}
|
||||
|
||||
void Dump(FILE *f) const;
|
||||
typedef std::vector<DYLIBInfo> collection;
|
||||
typedef collection::iterator iterator;
|
||||
typedef collection::const_iterator const_iterator;
|
||||
};
|
||||
struct InfoHeader
|
||||
{
|
||||
uint32_t version; /* == 1 in Mac OS X 10.4, == 2 in Mac OS 10.5 */
|
||||
uint32_t dylib_info_count;
|
||||
nub_addr_t dylib_info_addr;
|
||||
nub_addr_t notification;
|
||||
bool processDetachedFromSharedRegion;
|
||||
|
||||
InfoHeader() :
|
||||
version(0),
|
||||
dylib_info_count(0),
|
||||
dylib_info_addr(INVALID_NUB_ADDRESS),
|
||||
notification(INVALID_NUB_ADDRESS),
|
||||
processDetachedFromSharedRegion(false)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
version = 0;
|
||||
dylib_info_count = 0;
|
||||
dylib_info_addr = INVALID_NUB_ADDRESS;
|
||||
notification = INVALID_NUB_ADDRESS;
|
||||
processDetachedFromSharedRegion = false;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return version == 1 || version == 2;
|
||||
}
|
||||
};
|
||||
static nub_size_t CopySharedLibraryInfo(DYLIBInfo::collection& dylib_coll, DNBExecutableImageInfo **image_infos);
|
||||
static nub_size_t CopySharedInfoCallback(nub_process_t pid, struct DNBExecutableImageInfo **image_infos, nub_bool_t only_changed, void *baton);
|
||||
nub_process_t m_pid;
|
||||
uint32_t m_addr_size;
|
||||
nub_addr_t m_dyld_addr;
|
||||
nub_addr_t m_dyld_all_image_infos_addr;
|
||||
InfoHeader m_dylib_info_header;
|
||||
DYLIBInfo::collection m_current_dylibs; // Current shared libraries information
|
||||
DYLIBInfo::collection m_changed_dylibs; // Shared libraries that changed since last shared library update
|
||||
nub_break_t m_notify_break_id;
|
||||
mutable PThreadMutex m_dyld_info_mutex;
|
||||
};
|
||||
|
||||
#endif // #ifndef __MachDYLD_h__
|
|
@ -101,7 +101,8 @@ MachProcess::MachProcess() :
|
|||
m_name_to_addr_callback(NULL),
|
||||
m_name_to_addr_baton(NULL),
|
||||
m_image_infos_callback(NULL),
|
||||
m_image_infos_baton(NULL)
|
||||
m_image_infos_baton(NULL),
|
||||
m_did_exec (false)
|
||||
{
|
||||
DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
@ -199,9 +200,15 @@ MachProcess::SetCurrentThread(nub_thread_t tid)
|
|||
}
|
||||
|
||||
bool
|
||||
MachProcess::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const
|
||||
MachProcess::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
|
||||
{
|
||||
return m_thread_list.GetThreadStoppedReason(tid, stop_info);
|
||||
if (m_thread_list.GetThreadStoppedReason(tid, stop_info))
|
||||
{
|
||||
if (m_did_exec)
|
||||
stop_info->reason = eStopTypeExec;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -833,6 +840,11 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove)
|
|||
DNBBreakpoint *bp = m_breakpoints.FindByID (breakID);
|
||||
if (bp)
|
||||
{
|
||||
// After "exec" we might end up with a bunch of breakpoints that were disabled
|
||||
// manually, just ignore them
|
||||
if (!bp->IsEnabled())
|
||||
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);
|
||||
|
||||
|
@ -1155,13 +1167,62 @@ MachProcess::ExceptionMessageBundleComplete()
|
|||
DNBLogThreadedIf(LOG_EXCEPTIONS, "%s: %llu exception messages.", __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size());
|
||||
if (!m_exception_messages.empty())
|
||||
{
|
||||
m_did_exec = false;
|
||||
// First check for any SIGTRAP and make sure we didn't exec
|
||||
const task_t task = m_task.TaskPort();
|
||||
size_t i;
|
||||
if (m_pid != 0)
|
||||
{
|
||||
for (i=0; i<m_exception_messages.size(); ++i)
|
||||
{
|
||||
if (m_exception_messages[i].state.task_port == task)
|
||||
{
|
||||
const int signo = m_exception_messages[i].state.SoftSignal();
|
||||
if (signo == SIGTRAP)
|
||||
{
|
||||
// SIGTRAP could mean that we exec'ed. We need to check the
|
||||
// dyld all_image_infos.infoArray to see if it is NULL and if
|
||||
// so, say that we exec'ed.
|
||||
const nub_addr_t aii_addr = GetDYLDAllImageInfosAddress();
|
||||
if (aii_addr != INVALID_NUB_ADDRESS)
|
||||
{
|
||||
const nub_addr_t info_array_count_addr = aii_addr + 4;
|
||||
uint32_t info_array_count = 0;
|
||||
if (m_task.ReadMemory(info_array_count_addr, 4, &info_array_count) == 4)
|
||||
{
|
||||
DNBLog ("info_array_count is 0x%x", info_array_count);
|
||||
if (info_array_count == 0)
|
||||
m_did_exec = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DNBLog ("error: failed to read all_image_infos.infoArrayCount from 0x%8.8llx", info_array_count_addr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_did_exec)
|
||||
{
|
||||
cpu_type_t process_cpu_type = MachProcess::GetCPUTypeForLocalProcess (m_pid);
|
||||
if (m_cpu_type != process_cpu_type)
|
||||
{
|
||||
DNBLog ("arch changed from 0x%8.8x to 0x%8.8x", m_cpu_type, process_cpu_type);
|
||||
m_cpu_type = process_cpu_type;
|
||||
DNBArchProtocol::SetArchitecture (process_cpu_type);
|
||||
}
|
||||
m_thread_list.Clear();
|
||||
m_breakpoints.DisableAll();
|
||||
}
|
||||
}
|
||||
|
||||
// Let all threads recover from stopping and do any clean up based
|
||||
// on the previous thread state (if any).
|
||||
m_thread_list.ProcessDidStop(this);
|
||||
|
||||
// Let each thread know of any exceptions
|
||||
task_t task = m_task.TaskPort();
|
||||
size_t i;
|
||||
for (i=0; i<m_exception_messages.size(); ++i)
|
||||
{
|
||||
// Let the thread list figure use the MachProcess to forward all exceptions
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "DNBBreakpoint.h"
|
||||
#include "DNBError.h"
|
||||
#include "DNBThreadResumeActions.h"
|
||||
//#include "MachDYLD.h"
|
||||
#include "MachException.h"
|
||||
#include "MachVMMemory.h"
|
||||
#include "MachTask.h"
|
||||
|
@ -179,7 +178,7 @@ public:
|
|||
nub_thread_t GetCurrentThreadMachPort ();
|
||||
nub_thread_t SetCurrentThread (nub_thread_t tid);
|
||||
MachThreadList & GetThreadList() { return m_thread_list; }
|
||||
bool GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const;
|
||||
bool GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info);
|
||||
void DumpThreadStoppedReason(nub_thread_t tid) const;
|
||||
const char * GetThreadInfo (nub_thread_t tid) const;
|
||||
|
||||
|
@ -308,6 +307,7 @@ private:
|
|||
DNBCallbackCopyExecutableImageInfos
|
||||
m_image_infos_callback;
|
||||
void * m_image_infos_baton;
|
||||
bool m_did_exec;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1079,7 +1079,7 @@ RNBRemote::Initialize()
|
|||
|
||||
|
||||
bool
|
||||
RNBRemote::InitializeRegisters ()
|
||||
RNBRemote::InitializeRegisters (bool force)
|
||||
{
|
||||
pid_t pid = m_ctx.ProcessID();
|
||||
if (pid == INVALID_NUB_PROCESS)
|
||||
|
@ -1093,6 +1093,13 @@ RNBRemote::InitializeRegisters ()
|
|||
// registers to be discovered using multiple qRegisterInfo calls to get
|
||||
// all register information after the architecture for the process is
|
||||
// determined.
|
||||
if (force)
|
||||
{
|
||||
g_dynamic_register_map.clear();
|
||||
g_reg_entries = NULL;
|
||||
g_num_reg_entries = 0;
|
||||
}
|
||||
|
||||
if (g_dynamic_register_map.empty())
|
||||
{
|
||||
nub_size_t num_reg_sets = 0;
|
||||
|
@ -2381,6 +2388,10 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
|
|||
|
||||
if (DNBThreadGetStopReason (pid, tid, &tid_stop_info))
|
||||
{
|
||||
const bool did_exec = tid_stop_info.reason == eStopTypeExec;
|
||||
if (did_exec)
|
||||
RNBRemote::InitializeRegisters(true);
|
||||
|
||||
std::ostringstream ostrm;
|
||||
// Output the T packet with the thread
|
||||
ostrm << 'T';
|
||||
|
@ -2479,7 +2490,11 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
|
|||
}
|
||||
}
|
||||
|
||||
if (tid_stop_info.details.exception.type)
|
||||
if (did_exec)
|
||||
{
|
||||
ostrm << "reason:exec;";
|
||||
}
|
||||
else if (tid_stop_info.details.exception.type)
|
||||
{
|
||||
ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";";
|
||||
ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";";
|
||||
|
|
|
@ -129,7 +129,7 @@ public:
|
|||
|
||||
void Initialize();
|
||||
|
||||
bool InitializeRegisters ();
|
||||
bool InitializeRegisters (bool force = false);
|
||||
|
||||
rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL);
|
||||
rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL);
|
||||
|
|
Loading…
Reference in New Issue