summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2010-11-18 05:57:03 +0000
committerGreg Clayton <gclayton@apple.com>2010-11-18 05:57:03 +0000
commit3af9ea56d30ca97a5ce31cb1024501b324f8fa47 (patch)
tree6c613eee05c2d066b9a58e727f079725ffc34964
parent19ca5608db90bf06bfaba3e1b28af6ed68165d7d (diff)
downloadbcm5719-llvm-3af9ea56d30ca97a5ce31cb1024501b324f8fa47.tar.gz
bcm5719-llvm-3af9ea56d30ca97a5ce31cb1024501b324f8fa47.zip
Fixed Process::Halt() as it was broken for "process halt" after recent changes
to the DoHalt down in ProcessGDBRemote. I also moved the functionality that was in ProcessGDBRemote::DoHalt up into Process::Halt so not every class has to implement a tricky halt/resume on the internal state thread. The functionality is the same as it was before with two changes: - when we eat the event we now just reuse the event we consume when the private state thread is paused and set the interrupted bool on the event if needed - we also properly update the Process::m_public_state with the state of the event we consume. Prior to this, if you issued a "process halt" it would eat the event, not update the process state, and then produce a new event with the interrupted bit set and send it. Anyone listening to the event would get the stopped event with a process that whose state was set to "running". Fixed debugserver to not have to be spawned with the architecture of the inferior process. This worked fine for launching processes, but when attaching to processes by name or pid without a file in lldb, it would fail. Now debugserver can support multiple architectures for a native debug session on the current host. This currently means i386 and x86_64 are supported in the same binary and a x86_64 debugserver can attach to a i386 executable. This change involved a lot of changes to make sure we dynamically detect the correct registers for the inferior process. llvm-svn: 119680
-rw-r--r--lldb/include/lldb/API/SBThread.h24
-rw-r--r--lldb/include/lldb/Target/Process.h31
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj3
-rw-r--r--lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp55
-rw-r--r--lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h37
-rw-r--r--lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp5
-rw-r--r--lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h2
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp74
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h8
-rw-r--r--lldb/source/Target/Process.cpp87
-rw-r--r--lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj4
-rw-r--r--lldb/tools/debugserver/source/DNB.cpp95
-rw-r--r--lldb/tools/debugserver/source/DNB.h3
-rw-r--r--lldb/tools/debugserver/source/DNBArch.h29
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachProcess.cpp26
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachProcess.h3
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThread.cpp67
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThread.h12
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp33
-rw-r--r--lldb/tools/debugserver/source/MacOSX/MachThreadList.h2
-rw-r--r--lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h1
-rw-r--r--lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp50
-rw-r--r--lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h23
-rw-r--r--lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h1
-rw-r--r--lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp52
-rw-r--r--lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h23
-rw-r--r--lldb/tools/debugserver/source/RNBRemote.cpp304
-rw-r--r--lldb/tools/debugserver/source/RNBRemote.h18
-rw-r--r--lldb/tools/debugserver/source/debugserver.cpp35
29 files changed, 688 insertions, 419 deletions
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index 86a19ae0568..a41a3588907 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -35,6 +35,30 @@ public:
lldb::StopReason
GetStopReason();
+//
+// // Get the number of words associated with the stop reason.
+// size_t
+// GetStopReasonDataCount();
+//
+// //--------------------------------------------------------------------------
+// // Get information associated with a stop reason.
+// //
+// // Breakpoint and watchpoint stop reasons will have data that consists of
+// // pairs of breakpoint/watchpoint IDs followed by the breakpoint/watchpoint
+// // location IDs (they always come in pairs).
+// //
+// // Stop Reason Count Data Type
+// // ======================== ===== ==========================================
+// // eStopReasonNone 0
+// // eStopReasonTrace 0
+// // eStopReasonBreakpoint N duple: {breakpoint id, location id}
+// // eStopReasonWatchpoint N duple: {watchpoint id, location id}
+// // eStopReasonSignal 1 unix signal number
+// // eStopReasonException N exception data
+// // eStopReasonPlanComplete 0
+// //--------------------------------------------------------------------------
+// uint64_t
+// GetStopReasonDataAtIndex(uint32_t idx);
size_t
GetStopDescription (char *dst, size_t dst_len);
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 07f4d3de8e0..5b3b56b798d 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -628,6 +628,12 @@ public:
uint32_t
GetAddressByteSize();
+ void
+ SetAddressByteSize (uint32_t addr_byte_size)
+ {
+ m_addr_byte_size = addr_byte_size;
+ }
+
//------------------------------------------------------------------
/// Get the image information address for the current process.
///
@@ -1007,12 +1013,12 @@ public:
//------------------------------------------------------------------
/// Halts a running process.
///
- /// DoHalt should consume any process events that were delivered in the
- /// process of implementing the halt.
+ /// DoHalt should consume any process events that were delivered in
+ /// the process of implementing the halt.
///
/// @param[out] caused_stop
- /// If true, then this Halt caused the stop, otherwise, the process was
- /// already stopped.
+ /// If true, then this Halt caused the stop, otherwise, the
+ /// process was already stopped.
///
/// @return
/// Returns \b true if the process successfully halts, \b false
@@ -1633,8 +1639,17 @@ public:
/// @return
/// A valid ByteOrder enumeration, or eByteOrderInvalid.
//------------------------------------------------------------------
- virtual lldb::ByteOrder
- GetByteOrder () const = 0;
+ lldb::ByteOrder
+ GetByteOrder () const
+ {
+ return m_byte_order;
+ }
+
+ void
+ SetByteOrder (lldb::ByteOrder byte_order)
+ {
+ m_byte_order = byte_order;
+ }
const ConstString &
GetTargetTriple ()
@@ -1720,10 +1735,12 @@ protected:
std::auto_ptr<DynamicCheckerFunctions> m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use.
UnixSignals m_unix_signals; /// This is the current signal set for this process.
ConstString m_target_triple;
+ lldb::ByteOrder m_byte_order; /// The byte order of the process. Should be set in DidLaunch/DidAttach.
+ uint32_t m_addr_byte_size; /// The size in bytes of an address/pointer for the inferior process. Should be set in DidLaunch/DidAttach.
lldb::ABISP m_abi_sp;
lldb::InputReaderSP m_process_input_reader;
lldb_private::Communication m_stdio_communication;
- lldb_private::Mutex m_stdio_comm_mutex;
+ lldb_private::Mutex m_stdio_communication_mutex;
std::string m_stdout_data;
typedef std::map<lldb::LanguageType, lldb::LanguageRuntimeSP> LanguageRuntimeCollection;
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index ef4258c918c..2c13f0ca302 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -2452,6 +2452,7 @@
isa = PBXProject;
buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */;
compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
en,
@@ -2941,7 +2942,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- ONLY_ACTIVE_ARCH = YES;
+ ONLY_ACTIVE_ARCH = NO;
PREBINDING = NO;
VALID_ARCHS = "x86_64 i386";
};
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
index bc268b8e905..227a981b809 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -59,8 +59,10 @@ DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) :
m_dyld(),
m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
m_dyld_all_image_infos(),
+ m_dyld_all_image_infos_stop_id (UINT32_MAX),
m_break_id(LLDB_INVALID_BREAK_ID),
m_dyld_image_infos(),
+ m_dyld_image_infos_stop_id (UINT32_MAX),
m_mutex(Mutex::eMutexTypeRecursive)
{
}
@@ -83,10 +85,8 @@ void
DynamicLoaderMacOSXDYLD::DidAttach ()
{
PrivateInitialize(m_process);
- if (NeedToLocateDYLD ())
- LocateDYLD ();
+ LocateDYLD ();
SetNotificationBreakpoint ();
- UpdateAllImageInfos();
}
//------------------------------------------------------------------
@@ -99,10 +99,8 @@ void
DynamicLoaderMacOSXDYLD::DidLaunch ()
{
PrivateInitialize(m_process);
- if (NeedToLocateDYLD ())
- LocateDYLD ();
+ LocateDYLD ();
SetNotificationBreakpoint ();
- UpdateAllImageInfos();
}
@@ -401,12 +399,23 @@ bool
DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
{
Mutex::Locker locker(m_mutex);
+
+ // the all image infos is already valid for this process stop ID
+ if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
+ return true;
+
m_dyld_all_image_infos.Clear();
if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
{
- const ByteOrder endian = m_process->GetByteOrder();
- const uint32_t addr_size = m_process->GetAddressByteSize();
+ ByteOrder byte_order = m_process->GetByteOrder();
+ uint32_t addr_size = 4;
+ if (m_dyld_all_image_infos_addr > UINT32_MAX)
+ addr_size = 8;
+
uint8_t buf[256];
+ DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
+ uint32_t offset = 0;
+
const size_t count_v2 = sizeof (uint32_t) + // version
sizeof (uint32_t) + // infoArrayCount
addr_size + // infoArray
@@ -434,9 +443,23 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
Error error;
if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4)
{
- DataExtractor data(buf, 4, endian, addr_size);
- uint32_t offset = 0;
m_dyld_all_image_infos.version = data.GetU32(&offset);
+ // If anything in the high byte is set, we probably got the byte
+ // order incorrect (the process might not have it set correctly
+ // yet due to attaching to a program without a specified file).
+ if (m_dyld_all_image_infos.version & 0xff000000)
+ {
+ // We have guessed the wrong byte order. Swap it and try
+ // reading the version again.
+ if (byte_order == eByteOrderLittle)
+ byte_order = eByteOrderBig;
+ else
+ byte_order = eByteOrderLittle;
+
+ data.SetByteOrder (byte_order);
+ offset = 0;
+ m_dyld_all_image_infos.version = data.GetU32(&offset);
+ }
}
else
{
@@ -451,8 +474,7 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
if (bytes_read == count)
{
- DataExtractor data(buf, count, endian, addr_size);
- uint32_t offset = 0;
+ offset = 0;
m_dyld_all_image_infos.version = data.GetU32(&offset);
m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset);
@@ -486,6 +508,7 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure ()
m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
}
}
+ m_dyld_all_image_infos_stop_id = m_process->GetStopID();
return true;
}
}
@@ -504,6 +527,9 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
if (ReadAllImageInfosStructure ())
{
Mutex::Locker locker(m_mutex);
+ if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
+ m_dyld_image_infos.size();
+
uint32_t idx;
uint32_t i = 0;
DYLDImageInfo::collection old_dyld_all_image_infos;
@@ -511,8 +537,8 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
// If we made it here, we are assuming that the all dylib info data should
// be valid, lets read the info array.
- const ByteOrder endian = m_process->GetByteOrder();
- const uint32_t addr_size = m_process->GetAddressByteSize();
+ const ByteOrder endian = m_dyld.GetByteOrder();
+ const uint32_t addr_size = m_dyld.GetAddressByteSize();
if (m_dyld_all_image_infos.dylib_info_count > 0)
{
@@ -605,6 +631,7 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
if (log)
PutToLog(log.get());
}
+ m_dyld_image_infos_stop_id = m_process->GetStopID();
}
else
{
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
index 34ea8a46781..d8dbe711b3d 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
@@ -266,6 +266,41 @@ protected:
return uuid.IsValid();
}
+ uint32_t
+ GetAddressByteSize ()
+ {
+ if (header.cputype)
+ {
+ if (header.cputype & llvm::MachO::CPUArchABI64)
+ return 8;
+ else
+ return 4;
+ }
+ return 0;
+ }
+
+ lldb::ByteOrder
+ GetByteOrder()
+ {
+ switch (header.magic)
+ {
+ case llvm::MachO::HeaderMagic32: // MH_MAGIC
+ case llvm::MachO::HeaderMagic64: // MH_MAGIC_64
+ return lldb::eByteOrderHost;
+
+ case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
+ case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
+ if (lldb::eByteOrderHost == lldb::eByteOrderLittle)
+ return lldb::eByteOrderBig;
+ else
+ return lldb::eByteOrderLittle;
+ default:
+ assert (!"invalid header.magic value");
+ break;
+ }
+ return lldb::eByteOrderHost;
+ }
+
const Segment *
FindSegment (const lldb_private::ConstString &name) const;
@@ -348,8 +383,10 @@ protected:
DYLDImageInfo m_dyld; // Info about the curent dyld being used
lldb::addr_t m_dyld_all_image_infos_addr;
DYLDAllImageInfos m_dyld_all_image_infos;
+ uint32_t m_dyld_all_image_infos_stop_id;
lldb::user_id_t m_break_id;
DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information
+ uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for
mutable lldb_private::Mutex m_mutex;
lldb_private::Process::Notifications m_notification_callbacks;
diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
index 259c08072a1..b3933169841 100644
--- a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp
@@ -235,9 +235,7 @@ ProcessMacOSX::ProcessMacOSX(Target& target, Listener &listener) :
m_exception_messages (),
m_exception_messages_mutex (Mutex::eMutexTypeRecursive),
m_arch_spec (),
- m_dynamic_loader_ap (),
-// m_wait_thread (LLDB_INVALID_HOST_THREAD),
- m_byte_order (eByteOrderHost)
+ m_dynamic_loader_ap ()
{
}
@@ -676,6 +674,7 @@ ProcessMacOSX::RefreshStateAfterStop ()
Error
ProcessMacOSX::DoHalt (bool &caused_stop)
{
+ caused_stop = true;
return Signal (SIGSTOP);
}
diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
index 92d2c9c1653..4f8bdb930b7 100644
--- a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
+++ b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h
@@ -247,8 +247,6 @@ protected:
lldb_private::Mutex m_exception_messages_mutex; // Multithreaded protection for m_exception_messages
lldb_private::ArchSpec m_arch_spec;
std::auto_ptr<lldb_private::DynamicLoader> m_dynamic_loader_ap;
-// lldb::thread_t m_wait_thread;
- lldb::ByteOrder m_byte_order;
//----------------------------------------------------------------------
// Child process control
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index fcbd523699f..5496a02343a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -105,7 +105,6 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_dynamic_loader_ap (),
m_flags (0),
m_stdio_mutex (Mutex::eMutexTypeRecursive),
- m_byte_order (eByteOrderHost),
m_gdb_comm(),
m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
m_debugserver_thread (LLDB_INVALID_HOST_THREAD),
@@ -339,13 +338,13 @@ ProcessGDBRemote::WillLaunch (Module* module)
}
Error
-ProcessGDBRemote::WillAttach (lldb::pid_t pid)
+ProcessGDBRemote::WillAttachToProcessWithID (lldb::pid_t pid)
{
return WillLaunchOrAttach ();
}
Error
-ProcessGDBRemote::WillAttach (const char *process_name, bool wait_for_launch)
+ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
{
return WillLaunchOrAttach ();
}
@@ -556,8 +555,6 @@ ProcessGDBRemote::ConnectToDebugserver (const char *host_port)
if (response.IsOKPacket())
m_gdb_comm.SetAckMode (false);
}
-
- BuildDynamicRegisterInfo ();
}
return error;
}
@@ -574,22 +571,23 @@ ProcessGDBRemote::DidLaunchOrAttach ()
{
m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
- Module * exe_module = GetTarget().GetExecutableModule ().get();
+ BuildDynamicRegisterInfo ();
+
+ m_byte_order = m_gdb_comm.GetByteOrder();
+
+ Module * exe_module = GetTarget().GetExecutableModule().get();
assert(exe_module);
ObjectFile *exe_objfile = exe_module->GetObjectFile();
assert(exe_objfile);
- m_byte_order = exe_objfile->GetByteOrder();
- assert (m_byte_order != eByteOrderInvalid);
-
StreamString strm;
ArchSpec inferior_arch;
// See if the GDB server supports the qHostInfo information
const char *vendor = m_gdb_comm.GetVendorString().AsCString();
const char *os_type = m_gdb_comm.GetOSString().AsCString();
- ArchSpec arch_spec = GetTarget().GetArchitecture();
+ ArchSpec arch_spec (GetTarget().GetArchitecture());
if (arch_spec.IsValid() && arch_spec == ArchSpec ("arm"))
{
@@ -858,25 +856,8 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait
void
ProcessGDBRemote::DidAttach ()
{
- // If we haven't got an executable module yet, then we should make a dynamic loader, and
- // see if it can find the executable module for us. If we do have an executable module,
- // make sure it matches the process we've just attached to.
-
- ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
- if (!m_dynamic_loader_ap.get())
- {
- m_dynamic_loader_ap.reset(DynamicLoader::FindPlugin(this, "dynamic-loader.macosx-dyld"));
- }
-
if (m_dynamic_loader_ap.get())
m_dynamic_loader_ap->DidAttach();
-
- Module * new_exe_module = GetTarget().GetExecutableModule().get();
- if (new_exe_module == NULL)
- {
-
- }
-
DidLaunchOrAttach ();
}
@@ -1124,45 +1105,26 @@ Error
ProcessGDBRemote::DoHalt (bool &caused_stop)
{
Error error;
- caused_stop = false;
if (m_gdb_comm.IsRunning())
{
- PausePrivateStateThread();
+ caused_stop = true;
bool timed_out = false;
Mutex::Locker locker;
- if (m_gdb_comm.SendInterrupt (locker, 2, &timed_out))
- {
- EventSP event_sp;
- TimeValue timeout_time;
- timeout_time = TimeValue::Now();
- timeout_time.OffsetWithSeconds(2);
-
- StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
-
- if (!StateIsStoppedState (state))
- {
- LogSP log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf("ProcessGDBRemote::DoHalt() failed to stop after sending interrupt");
- error.SetErrorString ("Did not get stopped event after interrupt succeeded.");
- }
- else
- caused_stop = true;
- }
- else
+ if (!m_gdb_comm.SendInterrupt (locker, 2, &timed_out))
{
if (timed_out)
error.SetErrorString("timed out sending interrupt packet");
else
error.SetErrorString("unknown error sending interrupt packet");
}
-
- // Resume the private state thread at this point.
- ResumePrivateStateThread();
-
}
+ else
+ {
+ caused_stop = false;
+ }
+
return error;
}
@@ -1265,12 +1227,6 @@ ProcessGDBRemote::DoDestroy ()
return error;
}
-ByteOrder
-ProcessGDBRemote::GetByteOrder () const
-{
- return m_byte_order;
-}
-
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 1e85e9918a7..546f1054536 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -90,10 +90,10 @@ public:
DidLaunch ();
virtual lldb_private::Error
- WillAttach (lldb::pid_t pid);
+ WillAttachToProcessWithID (lldb::pid_t pid);
virtual lldb_private::Error
- WillAttach (const char *process_name, bool wait_for_launch);
+ WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
lldb_private::Error
WillLaunchOrAttach ();
@@ -215,9 +215,6 @@ public:
virtual lldb_private::Error
DisableWatchpoint (lldb_private::WatchpointLocation *wp_loc);
- virtual lldb::ByteOrder
- GetByteOrder () const;
-
virtual lldb_private::DynamicLoader *
GetDynamicLoader ();
@@ -322,7 +319,6 @@ protected:
std::auto_ptr<lldb_private::DynamicLoader> m_dynamic_loader_ap;
lldb_private::Flags m_flags; // Process specific flags (see eFlags enums)
lldb_private::Mutex m_stdio_mutex; // Multithreaded protection for stdio
- lldb::ByteOrder m_byte_order;
GDBRemoteCommunication m_gdb_comm;
lldb::pid_t m_debugserver_pid;
lldb::thread_t m_debugserver_thread;
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 749ae3ceb88..a86a4e10187 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -85,12 +85,19 @@ Process::Process(Target &target, Listener &listener) :
m_exit_string (),
m_thread_list (this),
m_notifications (),
- m_persistent_vars(),
- m_listener(listener),
+ m_image_tokens (),
+ m_listener (listener),
+ m_breakpoint_site_list (),
+ m_persistent_vars (),
+ m_dynamic_checkers_ap (),
m_unix_signals (),
+ m_target_triple (),
+ m_byte_order (eByteOrderHost),
+ m_addr_byte_size (0),
+ m_abi_sp (),
m_process_input_reader (),
m_stdio_communication ("lldb.process.stdio"),
- m_stdio_comm_mutex (Mutex::eMutexTypeRecursive),
+ m_stdio_communication_mutex (Mutex::eMutexTypeRecursive),
m_stdout_data ()
{
UpdateInstanceName();
@@ -1438,19 +1445,71 @@ Process::Halt ()
if (error.Success())
{
- bool caused_stop;
+
+ bool caused_stop = false;
+ EventSP event_sp;
+
+ // Pause our private state thread so we can ensure no one else eats
+ // the stop event out from under us.
+ PausePrivateStateThread();
+
+ // Ask the process subclass to actually halt our process
error = DoHalt(caused_stop);
if (error.Success())
{
- DidHalt();
+ // If "caused_stop" is true, then DoHalt stopped the process. If
+ // "caused_stop" is false, the process was already stopped.
+ // If the DoHalt caused the process to stop, then we want to catch
+ // this event and set the interrupted bool to true before we pass
+ // this along so clients know that the process was interrupted by
+ // a halt command.
if (caused_stop)
{
- ProcessEventData *new_data = new ProcessEventData (GetTarget().GetProcessSP(), eStateStopped);
- new_data->SetInterrupted(true);
- BroadcastEvent (eBroadcastBitStateChanged, new_data);
+ // Wait for 2 seconds for the process to stop.
+ TimeValue timeout_time;
+ timeout_time = TimeValue::Now();
+ timeout_time.OffsetWithSeconds(2);
+ StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp);
+
+ if (state == eStateInvalid)
+ {
+ // We timeout out and didn't get a stop event...
+ error.SetErrorString ("Halt timed out.");
+ }
+ else
+ {
+ // Since we are eating the event, we need to update our state
+ // otherwise the process state will not match reality...
+ SetPublicState(state);
+
+ if (StateIsStoppedState (state))
+ {
+ // We caused the process to interrupt itself, so mark this
+ // as such in the stop event so clients can tell an interrupted
+ // process from a natural stop
+ ProcessEventData::SetInterruptedInEvent (event_sp.get(), true);
+ }
+ else
+ {
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("Process::Halt() failed to stop, state is: %s", StateAsCString(state));
+ error.SetErrorString ("Did not get stopped event after halt.");
+ }
+ }
}
+ DidHalt();
+
}
-
+ // Resume our private state thread before we post the event (if any)
+ ResumePrivateStateThread();
+
+ // Post any event we might have consumed. If all goes well, we will have
+ // stopped the process, intercepted the event and set the interrupted
+ // bool in the event.
+ if (event_sp)
+ BroadcastEvent(event_sp);
+
}
return error;
}
@@ -1530,7 +1589,9 @@ Process::GetTarget () const
uint32_t
Process::GetAddressByteSize()
{
- return m_target.GetArchitecture().GetAddressByteSize();
+ if (m_addr_byte_size == 0)
+ return m_target.GetArchitecture().GetAddressByteSize();
+ return m_addr_byte_size;
}
bool
@@ -1603,8 +1664,8 @@ Process::ShouldBroadcastEvent (Event *event_ptr)
// If no thread has an opinion, we don't report it.
if (ProcessEventData::GetInterruptedFromEvent (event_ptr))
{
- if (log)
- log->Printf ("Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s", event_ptr, StateAsCString(state));
+ if (log)
+ log->Printf ("Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s", event_ptr, StateAsCString(state));
return true;
}
else
@@ -2074,7 +2135,7 @@ Process::GetArchSpecForExistingProcess (const char *process_name)
void
Process::AppendSTDOUT (const char * s, size_t len)
{
- Mutex::Locker locker (m_stdio_comm_mutex);
+ Mutex::Locker locker (m_stdio_communication_mutex);
m_stdout_data.append (s, len);
BroadcastEventIfUnique (eBroadcastBitSTDOUT);
diff --git a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj
index db7ad2692bb..3e8a4f84947 100644
--- a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj
+++ b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 264D5D581293835600ED4C01 /* DNBArch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D5D571293835600ED4C01 /* DNBArch.cpp */; };
2660D9CE1192280900958FBD /* StringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2660D9CC1192280900958FBD /* StringExtractor.cpp */; };
26CE05A7115C360D0022F371 /* DNBError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637DE0C71334A0024798E /* DNBError.cpp */; };
26CE05A8115C36170022F371 /* DNBThreadResumeActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */; };
@@ -48,6 +49,7 @@
260E7332114BFFE600D1DFB3 /* DNBThreadResumeActions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBThreadResumeActions.h; sourceTree = "<group>"; };
260FC7320E5B290400043FC9 /* debugnub-exports */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "debugnub-exports"; sourceTree = SOURCE_ROOT; };
26242C390DDBD33C0054A4CC /* debugserver-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "debugserver-entitlements.plist"; sourceTree = "<group>"; };
+ 264D5D571293835600ED4C01 /* DNBArch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArch.cpp; sourceTree = "<group>"; };
26593A060D4931CC001C9FE3 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; };
2660D9CC1192280900958FBD /* StringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractor.cpp; path = ../../source/Utility/StringExtractor.cpp; sourceTree = SOURCE_ROOT; };
2660D9CD1192280900958FBD /* StringExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractor.h; path = ../../source/Utility/StringExtractor.h; sourceTree = SOURCE_ROOT; };
@@ -190,6 +192,7 @@
26C637D70C71334A0024798E /* DNB.h */,
26C637D60C71334A0024798E /* DNB.cpp */,
26C637D80C71334A0024798E /* DNBArch.h */,
+ 264D5D571293835600ED4C01 /* DNBArch.cpp */,
26C637DA0C71334A0024798E /* DNBBreakpoint.h */,
26C637D90C71334A0024798E /* DNBBreakpoint.cpp */,
26C637DC0C71334A0024798E /* DNBDataRef.h */,
@@ -441,6 +444,7 @@
26CE05C5115C36590022F371 /* CFBundle.cpp in Sources */,
26CE05F1115C387C0022F371 /* PseudoTerminal.cpp in Sources */,
2660D9CE1192280900958FBD /* StringExtractor.cpp in Sources */,
+ 264D5D581293835600ED4C01 /* DNBArch.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp
index 948125b9714..17a17d32f0d 100644
--- a/lldb/tools/debugserver/source/DNB.cpp
+++ b/lldb/tools/debugserver/source/DNB.cpp
@@ -265,10 +265,8 @@ DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_st
DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm);
return INVALID_NUB_PROCESS;
}
- else
- {
- return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
- }
+
+ return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len);
}
nub_process_t
@@ -294,15 +292,20 @@ DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_
while (pid != INVALID_NUB_PROCESS)
{
// Wait for process to start up and hit entry point
- DNBLogThreadedIf (LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged "
- "| eEventProcessStoppedStateChanged, true, INFINITE)...",
- __FUNCTION__, pid);
+ DNBLogThreadedIf (LOG_PROCESS,
+ "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...",
+ __FUNCTION__,
+ pid);
nub_event_t set_events = DNBProcessWaitForEvents (pid,
- eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
- true, timeout);
- DNBLogThreadedIf (LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged "
- "| eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
- __FUNCTION__, pid, set_events);
+ eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged,
+ true,
+ timeout);
+
+ DNBLogThreadedIf (LOG_PROCESS,
+ "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x",
+ __FUNCTION__,
+ pid,
+ set_events);
if (set_events == 0)
{
@@ -320,29 +323,30 @@ DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_
switch (pid_state)
{
- default:
- case eStateInvalid:
- case eStateUnloaded:
- case eStateAttaching:
- case eStateLaunching:
- case eStateSuspended:
- break; // Ignore
-
- case eStateRunning:
- case eStateStepping:
- // Still waiting to stop at entry point...
- break;
-
- case eStateStopped:
- case eStateCrashed:
- return pid;
- case eStateDetached:
- case eStateExited:
- if (err_str && err_len > 0)
- snprintf(err_str, err_len, "process exited");
- return INVALID_NUB_PROCESS;
- }
- }
+ default:
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateSuspended:
+ break; // Ignore
+
+ case eStateRunning:
+ case eStateStepping:
+ // Still waiting to stop at entry point...
+ break;
+
+ case eStateStopped:
+ case eStateCrashed:
+ return pid;
+
+ case eStateDetached:
+ case eStateExited:
+ if (err_str && err_len > 0)
+ snprintf(err_str, err_len, "process exited");
+ return INVALID_NUB_PROCESS;
+ }
+ }
DNBProcessResetEvents(pid, set_events);
}
@@ -352,7 +356,7 @@ DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_
}
static size_t
-GetAllInfos(std::vector<struct kinfo_proc>& proc_infos)
+GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
{
size_t size;
int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
@@ -1722,7 +1726,7 @@ DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, stru
const DNBRegisterSetInfo *
DNBGetRegisterSetInfo (nub_size_t *num_reg_sets)
{
- return DNBArch::GetRegisterSetInfo (num_reg_sets);
+ return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets);
}
@@ -1998,3 +2002,20 @@ DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved
return false;
}
+
+void
+DNBInitialize()
+{
+ DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()");
+#if defined (__i386__) || defined (__x86_64__)
+ DNBArchImplI386::Initialize();
+ DNBArchImplX86_64::Initialize();
+#elif defined (__arm__)
+ DNBArchMachARM::Initialize();
+#endif
+}
+
+void
+DNBTerminate()
+{
+}
diff --git a/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h
index 4dadff2473b..921bbbfc23d 100644
--- a/lldb/tools/debugserver/source/DNB.h
+++ b/lldb/tools/debugserver/source/DNB.h
@@ -25,6 +25,9 @@ extern "C" {
typedef bool (*DNBShouldCancelCallback) (void *);
+void DNBInitialize ();
+void DNBTerminate ();
+
//----------------------------------------------------------------------
// Process control
//----------------------------------------------------------------------
diff --git a/lldb/tools/debugserver/source/DNBArch.h b/lldb/tools/debugserver/source/DNBArch.h
index 3eb2362aa0f..a0f18cd39c8 100644
--- a/lldb/tools/debugserver/source/DNBArch.h
+++ b/lldb/tools/debugserver/source/DNBArch.h
@@ -22,13 +22,39 @@
struct DNBRegisterValue;
struct DNBRegisterSetInfo;
+class DNBArchProtocol;
+class MachThread;
+
+typedef DNBArchProtocol * (* DNBArchCallbackCreate)(MachThread *thread);
+typedef const DNBRegisterSetInfo * (* DNBArchCallbackGetRegisterSetInfo)(nub_size_t *num_reg_sets);
+typedef const uint8_t * const (* DNBArchCallbackGetBreakpointOpcode)(nub_size_t byte_size);
+
+typedef struct DNBArchPluginInfoTag
+{
+ uint32_t cpu_type;
+ DNBArchCallbackCreate Create;
+ DNBArchCallbackGetRegisterSetInfo GetRegisterSetInfo;
+ DNBArchCallbackGetBreakpointOpcode GetBreakpointOpcode;
+} DNBArchPluginInfo;
class DNBArchProtocol
{
public:
- static const DNBRegisterSetInfo *
+ static DNBArchProtocol *
+ Create (MachThread *thread);
+
+ static const DNBRegisterSetInfo *
GetRegisterSetInfo (nub_size_t *num_reg_sets);
+ static const uint8_t * const
+ GetBreakpointOpcode (nub_size_t byte_size);
+
+ static void
+ RegisterArchPlugin (const DNBArchPluginInfo &arch_info);
+
+ static void
+ SetDefaultArchitecture (uint32_t cpu_type);
+
virtual bool GetRegisterValue (int set, int reg, DNBRegisterValue *value) = 0;
virtual bool SetRegisterValue (int set, int reg, const DNBRegisterValue *value) = 0;
virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len) = 0;
@@ -39,6 +65,7 @@ public:
virtual bool RegisterSetStateIsValid (int set) const = 0;
virtual uint64_t GetPC (uint64_t failValue) = 0; // Get program counter
+ virtual kern_return_t SetPC (uint64_t value) = 0;
virtual uint64_t GetSP (uint64_t failValue) = 0; // Get stack pointer
virtual void ThreadWillResume () = 0;
virtual bool ThreadDidStop () = 0;
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
index c5c1e7f6f0c..3ca7fe8abeb 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp
@@ -115,6 +115,7 @@ MachProcess::MachProcess() :
m_image_infos_baton(NULL)
{
DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__);
+ bzero(&m_arch_plugin_info, sizeof(m_arch_plugin_info));
}
MachProcess::~MachProcess()
@@ -208,7 +209,15 @@ MachProcess::GetThreadInfo(nub_thread_t tid) const
const DNBRegisterSetInfo *
MachProcess::GetRegisterSetInfo(nub_thread_t tid, nub_size_t *num_reg_sets ) const
{
- return DNBArch::GetRegisterSetInfo (num_reg_sets);
+ MachThread *thread = m_thread_list.GetThreadByID (tid);
+ if (thread)
+ {
+ DNBArchProtocol *arch = thread->GetArchProtocol();
+ if (arch)
+ return arch->GetRegisterSetInfo (num_reg_sets);
+ }
+ *num_reg_sets = 0;
+ return NULL;
}
bool
@@ -766,7 +775,7 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove)
const nub_size_t break_op_size = bp->ByteSize();
assert (break_op_size > 0);
- const uint8_t * const break_op = DNBArch::SoftwareBreakpointOpcode(bp->ByteSize());
+ const uint8_t * const break_op = DNBArchProtocol::GetBreakpointOpcode (bp->ByteSize());
if (break_op_size > 0)
{
// Clear a software breakoint instruction
@@ -954,7 +963,7 @@ MachProcess::EnableBreakpoint(nub_break_t breakID)
const nub_size_t break_op_size = bp->ByteSize();
assert (break_op_size != 0);
- const uint8_t * const break_op = DNBArch::SoftwareBreakpointOpcode(break_op_size);
+ const uint8_t * const break_op = DNBArchProtocol::GetBreakpointOpcode (break_op_size);
if (break_op_size > 0)
{
// Save the original opcode by reading it
@@ -1507,7 +1516,14 @@ MachProcess::LaunchForDebug
break;
case eLaunchFlavorPosixSpawn:
- m_pid = MachProcess::PosixSpawnChildForPTraceDebugging (path, argv, envp, stdio_path, this, disable_aslr, launch_err);
+ m_pid = MachProcess::PosixSpawnChildForPTraceDebugging (path,
+ m_arch_plugin_info.cpu_type,
+ argv,
+ envp,
+ stdio_path,
+ this,
+ disable_aslr,
+ launch_err);
break;
#if defined (__arm__)
@@ -1590,6 +1606,7 @@ pid_t
MachProcess::PosixSpawnChildForPTraceDebugging
(
const char *path,
+ cpu_type_t cpu_type,
char const *argv[],
char const *envp[],
const char *stdio_path,
@@ -1628,7 +1645,6 @@ MachProcess::PosixSpawnChildForPTraceDebugging
// We don't need to do this for ARM, and we really shouldn't now that we
// have multiple CPU subtypes and no posix_spawnattr call that allows us
// to set which CPU subtype to launch...
- cpu_type_t cpu_type = DNBArch::GetCPUType();
size_t ocount = 0;
err.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS))
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h
index fa0979d7e20..cff08bb4d68 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h
@@ -48,7 +48,7 @@ public:
pid_t AttachForDebug (pid_t pid, char *err_str, size_t err_len);
pid_t LaunchForDebug (const char *path, char const *argv[], char const *envp[], const char *stdio_path, nub_launch_flavor_t launch_flavor, int disable_aslr, DNBError &err);
static pid_t ForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], MachProcess* process, DNBError &err);
- static pid_t PosixSpawnChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], const char *stdio_path, MachProcess* process, int disable_aslr, DNBError& err);
+ static pid_t PosixSpawnChildForPTraceDebugging (const char *path, cpu_type_t cpu_type, char const *argv[], char const *envp[], const char *stdio_path, MachProcess* process, int disable_aslr, DNBError& err);
nub_addr_t GetDYLDAllImageInfosAddress ();
static const void * PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &err_str);
static void CleanupAfterAttach (const void *attach_token, bool success, DNBError &err_str);
@@ -254,6 +254,7 @@ private:
DNBCallbackCopyExecutableImageInfos
m_image_infos_callback;
void * m_image_infos_baton;
+ DNBArchPluginInfo m_arch_plugin_info;
};
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp
index ca2bf9b3b3a..ddd7746dad4 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp
@@ -31,14 +31,9 @@ MachThread::MachThread (MachProcess *process, thread_t thread) :
m_state_mutex (PTHREAD_MUTEX_RECURSIVE),
m_breakID (INVALID_NUB_BREAK_ID),
m_suspendCount (0),
- m_arch (this),
- m_regSets ()
+ m_arch_ap (DNBArchProtocol::Create (this)),
+ m_reg_sets (m_arch_ap->GetRegisterSetInfo (&n_num_reg_sets))
{
- nub_size_t num_reg_sets = 0;
- const DNBRegisterSetInfo *regSetInfo = m_arch.GetRegisterSetInfo(&num_reg_sets);
- if (num_reg_sets > 0)
- m_regSets.assign(regSetInfo, regSetInfo + num_reg_sets);
-
// Get the thread state so we know if a thread is in a state where we can't
// muck with it and also so we get the suspend count correct in case it was
// already suspended
@@ -251,34 +246,34 @@ MachThread::ThreadIDIsValid(thread_t thread)
bool
MachThread::GetRegisterState(int flavor, bool force)
{
- return m_arch.GetRegisterState(flavor, force) == KERN_SUCCESS;
+ return m_arch_ap->GetRegisterState(flavor, force) == KERN_SUCCESS;
}
bool
MachThread::SetRegisterState(int flavor)
{
- return m_arch.SetRegisterState(flavor) == KERN_SUCCESS;
+ return m_arch_ap->SetRegisterState(flavor) == KERN_SUCCESS;
}
uint64_t
MachThread::GetPC(uint64_t failValue)
{
// Get program counter
- return m_arch.GetPC(failValue);
+ return m_arch_ap->GetPC(failValue);
}
bool
MachThread::SetPC(uint64_t value)
{
// Set program counter
- return m_arch.SetPC(value);
+ return m_arch_ap->SetPC(value);
}
uint64_t
MachThread::GetSP(uint64_t failValue)
{
// Get stack pointer
- return m_arch.GetSP(failValue);
+ return m_arch_ap->GetSP(failValue);
}
nub_process_t
@@ -342,7 +337,7 @@ MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action)
Resume();
break;
}
- m_arch.ThreadWillResume();
+ m_arch_ap->ThreadWillResume();
m_stop_exception.Clear();
}
@@ -372,7 +367,7 @@ MachThread::ShouldStop(bool &step_more)
}
else
{
- if (m_arch.StepNotComplete())
+ if (m_arch_ap->StepNotComplete())
{
step_more = true;
return false;
@@ -426,7 +421,7 @@ MachThread::ThreadDidStop()
// When this method gets called, the process state is still in the
// state it was in while running so we can act accordingly.
- m_arch.ThreadDidStop();
+ m_arch_ap->ThreadDidStop();
// We may have suspended this thread so the primary thread could step
@@ -499,7 +494,7 @@ MachThread::NotifyException(MachException::Data& exc)
{
m_stop_exception = exc;
}
- bool handled = m_arch.NotifyException(exc);
+ bool handled = m_arch_ap->NotifyException(exc);
if (!handled)
{
handled = true;
@@ -551,25 +546,25 @@ MachThread::SetState(nub_state_t state)
uint32_t
MachThread::GetNumRegistersInSet(int regSet) const
{
- if (regSet < m_regSets.size())
- return m_regSets[regSet].num_registers;
+ if (regSet < n_num_reg_sets)
+ return m_reg_sets[regSet].num_registers;
return 0;
}
const char *
MachThread::GetRegisterSetName(int regSet) const
{
- if (regSet < m_regSets.size())
- return m_regSets[regSet].name;
+ if (regSet < n_num_reg_sets)
+ return m_reg_sets[regSet].name;
return NULL;
}
const DNBRegisterInfo *
MachThread::GetRegisterInfo(int regSet, int regIndex) const
{
- if (regSet < m_regSets.size())
- if (regIndex < m_regSets[regSet].num_registers)
- return &m_regSets[regSet].registers[regIndex];
+ if (regSet < n_num_reg_sets)
+ if (regIndex < m_reg_sets[regSet].num_registers)
+ return &m_reg_sets[regSet].registers[regIndex];
return NULL;
}
void
@@ -577,19 +572,19 @@ MachThread::DumpRegisterState(int regSet)
{
if (regSet == REGISTER_SET_ALL)
{
- for (regSet = 1; regSet < m_regSets.size(); regSet++)
+ for (regSet = 1; regSet < n_num_reg_sets; regSet++)
DumpRegisterState(regSet);
}
else
{
- if (m_arch.RegisterSetStateIsValid(regSet))
+ if (m_arch_ap->RegisterSetStateIsValid(regSet))
{
const size_t numRegisters = GetNumRegistersInSet(regSet);
size_t regIndex = 0;
DNBRegisterValueClass reg;
for (regIndex = 0; regIndex < numRegisters; ++regIndex)
{
- if (m_arch.GetRegisterValue(regSet, regIndex, &reg))
+ if (m_arch_ap->GetRegisterValue(regSet, regIndex, &reg))
{
reg.Dump(NULL, NULL);
}
@@ -605,39 +600,39 @@ MachThread::DumpRegisterState(int regSet)
const DNBRegisterSetInfo *
MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets ) const
{
- *num_reg_sets = m_regSets.size();
- return &m_regSets[0];
+ *num_reg_sets = n_num_reg_sets;
+ return &m_reg_sets[0];
}
bool
MachThread::GetRegisterValue ( uint32_t set, uint32_t reg, DNBRegisterValue *value )
{
- return m_arch.GetRegisterValue(set, reg, value);
+ return m_arch_ap->GetRegisterValue(set, reg, value);
}
bool
MachThread::SetRegisterValue ( uint32_t set, uint32_t reg, const DNBRegisterValue *value )
{
- return m_arch.SetRegisterValue(set, reg, value);
+ return m_arch_ap->SetRegisterValue(set, reg, value);
}
nub_size_t
MachThread::GetRegisterContext (void *buf, nub_size_t buf_len)
{
- return m_arch.GetRegisterContext(buf, buf_len);
+ return m_arch_ap->GetRegisterContext(buf, buf_len);
}
nub_size_t
MachThread::SetRegisterContext (const void *buf, nub_size_t buf_len)
{
- return m_arch.SetRegisterContext(buf, buf_len);
+ return m_arch_ap->SetRegisterContext(buf, buf_len);
}
uint32_t
MachThread::EnableHardwareBreakpoint (const DNBBreakpoint *bp)
{
if (bp != NULL && bp->IsBreakpoint())
- return m_arch.EnableHardwareBreakpoint(bp->Address(), bp->ByteSize());
+ return m_arch_ap->EnableHardwareBreakpoint(bp->Address(), bp->ByteSize());
return INVALID_NUB_HW_INDEX;
}
@@ -645,7 +640,7 @@ uint32_t
MachThread::EnableHardwareWatchpoint (const DNBBreakpoint *wp)
{
if (wp != NULL && wp->IsWatchpoint())
- return m_arch.EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite());
+ return m_arch_ap->EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite());
return INVALID_NUB_HW_INDEX;
}
@@ -653,7 +648,7 @@ bool
MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp)
{
if (bp != NULL && bp->IsHardware())
- return m_arch.DisableHardwareBreakpoint(bp->GetHardwareIndex());
+ return m_arch_ap->DisableHardwareBreakpoint(bp->GetHardwareIndex());
return false;
}
@@ -661,7 +656,7 @@ bool
MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp)
{
if (wp != NULL && wp->IsHardware())
- return m_arch.DisableHardwareWatchpoint(wp->GetHardwareIndex());
+ return m_arch_ap->DisableHardwareWatchpoint(wp->GetHardwareIndex());
return false;
}
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h
index f7f2ce8b1ab..0b2a8bf1ff9 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachThread.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h
@@ -95,6 +95,13 @@ public:
GetBasicInfo ();
const char * GetBasicInfoAsString () const;
const char * GetName ();
+
+ DNBArchProtocol*
+ GetArchProtocol()
+ {
+ return m_arch_ap.get();
+ }
+
protected:
static bool GetBasicInfo(thread_t threadID, struct thread_basic_info *basic_info);
@@ -113,8 +120,9 @@ protected:
struct thread_basic_info m_basicInfo; // Basic information for a thread used to see if a thread is valid
uint32_t m_suspendCount; // The current suspend count
MachException::Data m_stop_exception; // The best exception that describes why this thread is stopped
- DNBArch m_arch; // Arch specific information for register state and more
- std::vector<DNBRegisterSetInfo> m_regSets; // Register set information for this thread
+ std::auto_ptr<DNBArchProtocol> m_arch_ap; // Arch specific information for register state and more
+ const DNBRegisterSetInfo *const m_reg_sets; // Register set information for this thread
+ nub_size_t n_num_reg_sets;
#ifdef THREAD_IDENTIFIER_INFO_COUNT
thread_identifier_info_data_t m_ident_info;
struct proc_threadinfo m_proc_threadinfo;
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp
index db2a00a304a..7a5e9bb8588 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp
@@ -12,6 +12,9 @@
//===----------------------------------------------------------------------===//
#include "MachThreadList.h"
+
+#include <sys/sysctl.h>
+
#include "DNBLog.h"
#include "DNBThreadResumeActions.h"
#include "MachProcess.h"
@@ -104,6 +107,15 @@ MachThreadList::GetThreadInfo(nub_thread_t tid) const
return NULL;
}
+MachThread *
+MachThreadList::GetThreadByID (nub_thread_t tid) const
+{
+ uint32_t idx = GetThreadIndexByID(tid);
+ if (idx < m_threads.size())
+ return m_threads[idx].get();
+ return NULL;
+}
+
bool
MachThreadList::GetRegisterValue ( nub_thread_t tid, uint32_t reg_set_idx, uint32_t reg_idx, DNBRegisterValue *reg_value ) const
{
@@ -202,9 +214,28 @@ uint32_t
MachThreadList::UpdateThreadList(MachProcess *process, bool update)
{
// locker will keep a mutex locked until it goes out of scope
- DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThreadList::UpdateThreadList (pid = %4.4x, update = %u )", process->ProcessID(), update);
+ DNBLogThreadedIf (LOG_THREAD, "MachThreadList::UpdateThreadList (pid = %4.4x, update = %u) process stop count = %u", process->ProcessID(), update, process->StopCount());
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
+#if defined (__i386__) || defined (__x86_64__)
+ if (process->StopCount() == 0)
+ {
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process->ProcessID() };
+ struct kinfo_proc processInfo;
+ size_t bufsize = sizeof(processInfo);
+ bool is_64_bit = false;
+ if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0)
+ {
+ if (processInfo.kp_proc.p_flag & P_LP64)
+ is_64_bit = true;
+ }
+ if (is_64_bit)
+ DNBArchProtocol::SetDefaultArchitecture(CPU_TYPE_X86_64);
+ else
+ DNBArchProtocol::SetDefaultArchitecture(CPU_TYPE_I386);
+ }
+#endif
+
if (m_threads.empty() || update)
{
thread_array_t thread_list = NULL;
diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h
index 5c813886569..1a17618a7e3 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h
@@ -55,6 +55,8 @@ public:
bool DisableHardwareWatchpoint (const DNBBreakpoint *wp) const;
uint32_t GetThreadIndexForThreadStoppedWithSignal (const int signo) const;
+ MachThread * GetThreadByID (nub_thread_t tid) const;
+
protected:
typedef std::vector<MachThreadSP> collection;
typedef collection::iterator iterator;
diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h
index f012caa1828..9aff44e5dbc 100644
--- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h
+++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h
@@ -235,6 +235,5 @@ protected:
};
-typedef DNBArchMachARM DNBArch;
#endif // #if defined (__arm__)
#endif // #ifndef __DebugNubArchMachARM_h__
diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
index 0a0601f6378..1222b809904 100644
--- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined (__i386__)
+#if defined (__i386__) || defined (__x86_64__)
#include <sys/cdefs.h>
@@ -20,8 +20,6 @@
#include "MachThread.h"
#include "MachProcess.h"
-static const uint8_t g_breakpoint_opcode[] = { 0xCC };
-
enum
{
gpr_eax = 0,
@@ -187,21 +185,6 @@ enum
gdb_mm7 = 48
};
-
-const uint8_t * const
-DNBArchImplI386::SoftwareBreakpointOpcode (nub_size_t byte_size)
-{
- if (byte_size == 1)
- return g_breakpoint_opcode;
- return NULL;
-}
-
-uint32_t
-DNBArchImplI386::GetCPUType()
-{
- return CPU_TYPE_I386;
-}
-
uint64_t
DNBArchImplI386::GetPC(uint64_t failValue)
{
@@ -589,6 +572,21 @@ DNBArchImplI386::g_reg_sets[] =
const size_t DNBArchImplI386::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo);
+DNBArchProtocol *
+DNBArchImplI386::Create (MachThread *thread)
+{
+ return new DNBArchImplI386 (thread);
+}
+
+const uint8_t * const
+DNBArchImplI386::SoftwareBreakpointOpcode (nub_size_t byte_size)
+{
+ static const uint8_t g_breakpoint_opcode[] = { 0xCC };
+ if (byte_size == 1)
+ return g_breakpoint_opcode;
+ return NULL;
+}
+
const DNBRegisterSetInfo *
DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets)
{
@@ -596,6 +594,22 @@ DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets)
return g_reg_sets;
}
+
+void
+DNBArchImplI386::Initialize()
+{
+ DNBArchPluginInfo arch_plugin_info =
+ {
+ CPU_TYPE_I386,
+ DNBArchImplI386::Create,
+ DNBArchImplI386::GetRegisterSetInfo,
+ DNBArchImplI386::SoftwareBreakpointOpcode
+ };
+
+ // Register this arch plug-in with the main protocol class
+ DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
+}
+
bool
DNBArchImplI386::GetRegisterValue(int set, int reg, DNBRegisterValue *value)
{
diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
index 2b47e09cdf3..e0fcc199b5e 100644
--- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
+++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h
@@ -14,7 +14,7 @@
#ifndef __DNBArchImplI386_h__
#define __DNBArchImplI386_h__
-#if defined (__i386__)
+#if defined (__i386__) || defined (__x86_64__)
#include "DNBArch.h"
#include <mach/mach_types.h>
@@ -34,9 +34,8 @@ public:
virtual ~DNBArchImplI386()
{
}
-
- static const DNBRegisterSetInfo *
- GetRegisterSetInfo(nub_size_t *num_reg_sets);
+
+ static void Initialize();
virtual bool GetRegisterValue(int set, int reg, DNBRegisterValue *value);
virtual bool SetRegisterValue(int set, int reg, const DNBRegisterValue *value);
@@ -53,9 +52,6 @@ public:
virtual bool ThreadDidStop();
virtual bool NotifyException(MachException::Data& exc);
- static const uint8_t * const SoftwareBreakpointOpcode (nub_size_t byte_size);
- static uint32_t GetCPUType();
-
protected:
kern_return_t EnableHardwareSingleStep (bool enable);
@@ -186,11 +182,18 @@ protected:
kern_return_t SetFPUState ();
kern_return_t SetEXCState ();
+ static DNBArchProtocol *
+ Create (MachThread *thread);
+
+ static const uint8_t * const
+ SoftwareBreakpointOpcode (nub_size_t byte_size);
+
+ static const DNBRegisterSetInfo *
+ GetRegisterSetInfo(nub_size_t *num_reg_sets);
+
MachThread *m_thread;
State m_state;
};
-typedef DNBArchImplI386 DNBArch;
-
-#endif // #if defined (__i386__)
+#endif // #if defined (__i386__) || defined (__x86_64__)
#endif // #ifndef __DNBArchImplI386_h__
diff --git a/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h
index 6263407460a..a787d14d8d4 100644
--- a/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h
+++ b/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h
@@ -175,6 +175,5 @@ protected:
State m_state;
};
-typedef DNBArchMachPPC DNBArch;
#endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__)
#endif // #ifndef __DebugNubArchMachPPC_h__
diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
index 1f18156650c..fde3be6ab5d 100644
--- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined (__x86_64__)
+#if defined (__i386__) || defined (__x86_64__)
#include <sys/cdefs.h>
@@ -20,22 +20,6 @@
#include "MachThread.h"
#include "MachProcess.h"
-static const uint8_t g_breakpoint_opcode[] = { 0xCC };
-
-const uint8_t * const
-DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size)
-{
- if (byte_size == 1)
- return g_breakpoint_opcode;
- return NULL;
-}
-
-uint32_t
-DNBArchImplX86_64::GetCPUType()
-{
- return CPU_TYPE_X86_64;
-}
-
uint64_t
DNBArchImplX86_64::GetPC(uint64_t failValue)
{
@@ -718,13 +702,43 @@ DNBArchImplX86_64::g_reg_sets[] =
const size_t DNBArchImplX86_64::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo);
+DNBArchProtocol *
+DNBArchImplX86_64::Create (MachThread *thread)
+{
+ return new DNBArchImplX86_64 (thread);
+}
+
+const uint8_t * const
+DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size)
+{
+ static const uint8_t g_breakpoint_opcode[] = { 0xCC };
+ if (byte_size == 1)
+ return g_breakpoint_opcode;
+ return NULL;
+}
+
const DNBRegisterSetInfo *
-DNBArchImplX86_64::GetRegisterSetInfo (nub_size_t *num_reg_sets)
+DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets)
{
*num_reg_sets = k_num_register_sets;
return g_reg_sets;
}
+void
+DNBArchImplX86_64::Initialize()
+{
+ DNBArchPluginInfo arch_plugin_info =
+ {
+ CPU_TYPE_X86_64,
+ DNBArchImplX86_64::Create,
+ DNBArchImplX86_64::GetRegisterSetInfo,
+ DNBArchImplX86_64::SoftwareBreakpointOpcode
+ };
+
+ // Register this arch plug-in with the main protocol class
+ DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
+}
+
bool
DNBArchImplX86_64::GetRegisterValue(int set, int reg, DNBRegisterValue *value)
{
@@ -1032,4 +1046,4 @@ DNBArchImplX86_64::RegisterSetStateIsValid (int set) const
-#endif // #if defined (__i386__)
+#endif // #if defined (__i386__) || defined (__x86_64__)
diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h
index def263fec5e..584943c85c7 100644
--- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h
+++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h
@@ -14,8 +14,7 @@
#ifndef __DNBArchImplX86_64_h__
#define __DNBArchImplX86_64_h__
-//#if defined (__i386__)
-#if defined(__x86_64__)
+#if defined (__i386__) || defined (__x86_64__)
#include "DNBArch.h"
#include <mach/mach_types.h>
#include <mach/thread_status.h>
@@ -35,9 +34,7 @@ public:
{
}
- static const DNBRegisterSetInfo *
- GetRegisterSetInfo(nub_size_t *num_reg_sets);
-
+ static void Initialize();
virtual bool GetRegisterValue(int set, int reg, DNBRegisterValue *value);
virtual bool SetRegisterValue(int set, int reg, const DNBRegisterValue *value);
virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len);
@@ -54,9 +51,6 @@ public:
virtual bool ThreadDidStop();
virtual bool NotifyException(MachException::Data& exc);
- static const uint8_t * const SoftwareBreakpointOpcode (nub_size_t byte_size);
- static uint32_t GetCPUType();
-
protected:
kern_return_t EnableHardwareSingleStep (bool enable);
@@ -189,11 +183,18 @@ protected:
kern_return_t SetFPUState ();
kern_return_t SetEXCState ();
+ static DNBArchProtocol *
+ Create (MachThread *thread);
+
+ static const uint8_t * const
+ SoftwareBreakpointOpcode (nub_size_t byte_size);
+
+ static const DNBRegisterSetInfo *
+ GetRegisterSetInfo(nub_size_t *num_reg_sets);
+
MachThread *m_thread;
State m_state;
};
-typedef DNBArchImplX86_64 DNBArch;
-
-#endif // #if defined (__x86_64__)
+#endif // #if defined (__i386__) || defined (__x86_64__)
#endif // #ifndef __DNBArchImplX86_64_h__
diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp
index 7b2ba3335be..bb8c59ea0eb 100644
--- a/lldb/tools/debugserver/source/RNBRemote.cpp
+++ b/lldb/tools/debugserver/source/RNBRemote.cpp
@@ -60,11 +60,10 @@
extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
-RNBRemote::RNBRemote (bool use_native_regs) :
- m_ctx(),
- m_comm(),
- m_extended_mode(false),
- m_noack_mode(false),
+RNBRemote::RNBRemote (bool use_native_regs, const char *arch) :
+ m_ctx (),
+ m_comm (),
+ m_arch (),
m_continue_thread(-1),
m_thread(-1),
m_mutex(),
@@ -75,10 +74,14 @@ RNBRemote::RNBRemote (bool use_native_regs) :
m_rx_pthread(0),
m_breakpoints(),
m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4),
+ m_extended_mode(false),
+ m_noack_mode(false),
m_use_native_regs (use_native_regs)
{
DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
CreatePacketTable ();
+ if (arch && arch[0])
+ m_arch.assign (arch);
}
@@ -803,12 +806,10 @@ RegisterEntryNotAvailable (register_map_entry_t *reg_entry)
reg_entry->nub_info.reg_gdb = INVALID_NUB_REGNUM;
}
-#if defined (__arm__)
//----------------------------------------------------------------------
// ARM regiseter sets as gdb knows them
//----------------------------------------------------------------------
-
register_map_entry_t
g_gdb_register_map_arm[] =
{
@@ -873,32 +874,6 @@ g_gdb_register_map_arm[] =
{ 58, 4, "fpscr", {0}, NULL, 0}
};
-void
-RNBRemote::InitializeRegisters (int use_native_registers)
-{
- if (use_native_registers)
- {
- RNBRemote::InitializeNativeRegisters();
- }
- else
- {
- const size_t num_regs = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
- for (uint32_t i=0; i<num_regs; ++i)
- {
- if (!DNBGetRegisterInfoByName (g_gdb_register_map_arm[i].gdb_name, &g_gdb_register_map_arm[i].nub_info))
- {
- RegisterEntryNotAvailable (&g_gdb_register_map_arm[i]);
- assert (g_gdb_register_map_arm[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
- }
- }
- g_reg_entries = g_gdb_register_map_arm;
- g_num_reg_entries = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
- }
-}
-
-
-#elif defined (__i386__)
-
register_map_entry_t
g_gdb_register_map_i386[] =
{
@@ -945,32 +920,6 @@ g_gdb_register_map_i386[] =
{ 40, 4, "mxcsr" , {0}, NULL, 0 },
};
-void
-RNBRemote::InitializeRegisters (int use_native_registers)
-{
- if (use_native_registers)
- {
- RNBRemote::InitializeNativeRegisters();
- }
- else
- {
- const size_t num_regs = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
- for (uint32_t i=0; i<num_regs; ++i)
- {
- if (!DNBGetRegisterInfoByName (g_gdb_register_map_i386[i].gdb_name, &g_gdb_register_map_i386[i].nub_info))
- {
- RegisterEntryNotAvailable (&g_gdb_register_map_i386[i]);
- assert (g_gdb_register_map_i386[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
- }
- }
- g_reg_entries = g_gdb_register_map_i386;
- g_num_reg_entries = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
- }
-}
-
-
-#elif defined (__x86_64__)
-
register_map_entry_t
g_gdb_register_map_x86_64[] =
{
@@ -1033,86 +982,113 @@ g_gdb_register_map_x86_64[] =
{ 56, 4, "mxcsr" , {0}, NULL, 0 }
};
-void
-RNBRemote::InitializeRegisters (int use_native_registers)
-{
- if (use_native_registers)
- {
- RNBRemote::InitializeNativeRegisters();
- }
- else
- {
- const size_t num_regs = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
- for (uint32_t i=0; i<num_regs; ++i)
- {
- if (!DNBGetRegisterInfoByName (g_gdb_register_map_x86_64[i].gdb_name, &g_gdb_register_map_x86_64[i].nub_info))
- {
- RegisterEntryNotAvailable (&g_gdb_register_map_x86_64[i]);
- assert (g_gdb_register_map_x86_64[i].gdb_size < MAX_REGISTER_BYTE_SIZE);
- }
- }
- g_reg_entries = g_gdb_register_map_x86_64;
- g_num_reg_entries = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
- }
-}
-
-
-#else
void
-RNBRemote::InitializeRegisters (int use_native_registers)
+RNBRemote::Initialize()
{
- // No choice, we don't have a GDB register definition for this arch.
- RNBRemote::InitializeNativeRegisters();
+ DNBInitialize();
}
-#endif
-
-void
-RNBRemote::InitializeNativeRegisters()
+bool
+RNBRemote::InitializeRegisters ()
{
- if (g_dynamic_register_map.empty())
- {
- nub_size_t num_reg_sets = 0;
- const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets);
-
- assert (num_reg_sets > 0 && reg_sets != NULL);
+ pid_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return false;
- uint32_t regnum = 0;
- for (nub_size_t set = 0; set < num_reg_sets; ++set)
+ if (m_use_native_regs)
+ {
+ DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface (%s)", __FUNCTION__, m_arch.c_str());
+ // Discover the registers by querying the DNB interface and letting it
+ // state the registers that it would like to export. This allows the
+ // registers to be discovered using multiple qRegisterInfo calls to get
+ // all register information after the architecture for the process is
+ // determined.
+ if (g_dynamic_register_map.empty())
{
- if (reg_sets[set].registers == NULL)
- continue;
+ nub_size_t num_reg_sets = 0;
+ const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets);
- for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg)
+ assert (num_reg_sets > 0 && reg_sets != NULL);
+
+ uint32_t regnum = 0;
+ for (nub_size_t set = 0; set < num_reg_sets; ++set)
{
- register_map_entry_t reg_entry = {
- regnum++, // register number starts at zero and goes up with no gaps
- reg_sets[set].registers[reg].size, // register size in bytes
- reg_sets[set].registers[reg].name, // register name
- reg_sets[set].registers[reg], // DNBRegisterInfo
- NULL, // Value to print if case we fail to reg this register (if this is NULL, we will return an error)
- reg_sets[set].registers[reg].reg_generic != INVALID_NUB_REGNUM};
-
- g_dynamic_register_map.push_back (reg_entry);
+ if (reg_sets[set].registers == NULL)
+ continue;
+
+ for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg)
+ {
+ register_map_entry_t reg_entry = {
+ regnum++, // register number starts at zero and goes up with no gaps
+ reg_sets[set].registers[reg].size, // register size in bytes
+ reg_sets[set].registers[reg].name, // register name
+ reg_sets[set].registers[reg], // DNBRegisterInfo
+ NULL, // Value to print if case we fail to reg this register (if this is NULL, we will return an error)
+ reg_sets[set].registers[reg].reg_generic != INVALID_NUB_REGNUM};
+
+ g_dynamic_register_map.push_back (reg_entry);
+ }
}
+ g_reg_entries = g_dynamic_register_map.data();
+ g_num_reg_entries = g_dynamic_register_map.size();
}
- g_reg_entries = g_dynamic_register_map.data();
- g_num_reg_entries = g_dynamic_register_map.size();
+ return true;
}
-}
-
-
-const register_map_entry_t *
-register_mapping_by_regname (const char *n)
-{
- for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
+ else
{
- if (strcmp (g_reg_entries[reg].gdb_name, n) == 0)
- return &g_reg_entries[reg];
+ DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting gdb registers (%s)", __FUNCTION__, m_arch.c_str());
+#if defined (__i386__) || defined (__x86_64__)
+ if (m_arch.compare("x86_64") == 0)
+ {
+ const size_t num_regs = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
+ for (uint32_t i=0; i<num_regs; ++i)
+ {
+ if (!DNBGetRegisterInfoByName (g_gdb_register_map_x86_64[i].gdb_name, &g_gdb_register_map_x86_64[i].nub_info))
+ {
+ RegisterEntryNotAvailable (&g_gdb_register_map_x86_64[i]);
+ assert (g_gdb_register_map_x86_64[i].gdb_size < MAX_REGISTER_BYTE_SIZE);
+ }
+ }
+ g_reg_entries = g_gdb_register_map_x86_64;
+ g_num_reg_entries = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
+ return true;
+ }
+ else if (m_arch.compare("i386") == 0)
+ {
+ const size_t num_regs = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
+ for (uint32_t i=0; i<num_regs; ++i)
+ {
+ if (!DNBGetRegisterInfoByName (g_gdb_register_map_i386[i].gdb_name, &g_gdb_register_map_i386[i].nub_info))
+ {
+ RegisterEntryNotAvailable (&g_gdb_register_map_i386[i]);
+ assert (g_gdb_register_map_i386[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
+ }
+ }
+ g_reg_entries = g_gdb_register_map_i386;
+ g_num_reg_entries = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
+ return true;
+ }
+#elif defined (__arm__)
+ if (m_arch.find ("arm") == 0)
+ {
+ const size_t num_regs = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
+ for (uint32_t i=0; i<num_regs; ++i)
+ {
+ if (!DNBGetRegisterInfoByName (g_gdb_register_map_arm[i].gdb_name, &g_gdb_register_map_arm[i].nub_info))
+ {
+ RegisterEntryNotAvailable (&g_gdb_register_map_arm[i]);
+ assert (g_gdb_register_map_arm[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
+ }
+ }
+ g_reg_entries = g_gdb_register_map_arm;
+ g_num_reg_entries = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
+ return true;
+ }
+#endif
}
- return NULL;
+ return false;
}
/* The inferior has stopped executing; send a packet
@@ -1121,7 +1097,7 @@ register_mapping_by_regname (const char *n)
void
RNBRemote::NotifyThatProcessStopped (void)
{
- RNBRemote::HandlePacket_last_signal ("");
+ RNBRemote::HandlePacket_last_signal (NULL);
return;
}
@@ -1396,6 +1372,9 @@ RNBRemote::HandlePacket_qC (const char *p)
rnb_err_t
RNBRemote::HandlePacket_qRegisterInfo (const char *p)
{
+ if (g_num_reg_entries == 0)
+ InitializeRegisters ();
+
p += strlen ("qRegisterInfo");
nub_size_t num_reg_sets = 0;
@@ -1951,6 +1930,9 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
if (thread_ident_info.dispatch_qaddr != 0)
ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
}
+ if (g_num_reg_entries == 0)
+ InitializeRegisters ();
+
DNBRegisterValue reg_value;
for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
{
@@ -2002,45 +1984,45 @@ RNBRemote::HandlePacket_last_signal (const char *unused)
case eStateSuspended:
case eStateStopped:
case eStateCrashed:
- {
- nub_thread_t tid = DNBProcessGetCurrentThread (pid);
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
- SetCurrentThread (tid);
+ {
+ nub_thread_t tid = DNBProcessGetCurrentThread (pid);
+ // Make sure we set the current thread so g and p packets return
+ // the data the gdb will expect.
+ SetCurrentThread (tid);
- SendStopReplyPacketForThread (tid);
- }
+ SendStopReplyPacketForThread (tid);
+ }
break;
case eStateInvalid:
case eStateUnloaded:
case eStateExited:
- {
- char pid_exited_packet[16] = "";
- int pid_status = 0;
- // Process exited with exit status
- if (!DNBProcessGetExitStatus(pid, &pid_status))
- pid_status = 0;
-
- if (pid_status)
{
- if (WIFEXITED (pid_status))
- snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status));
- else if (WIFSIGNALED (pid_status))
- snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status));
- else if (WIFSTOPPED (pid_status))
- snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status));
- }
+ char pid_exited_packet[16] = "";
+ int pid_status = 0;
+ // Process exited with exit status
+ if (!DNBProcessGetExitStatus(pid, &pid_status))
+ pid_status = 0;
- // If we have an empty exit packet, lets fill one in to be safe.
- if (!pid_exited_packet[0])
- {
- strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1);
- pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0';
- }
+ if (pid_status)
+ {
+ if (WIFEXITED (pid_status))
+ snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status));
+ else if (WIFSIGNALED (pid_status))
+ snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status));
+ else if (WIFSTOPPED (pid_status))
+ snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status));
+ }
- return SendPacket (pid_exited_packet);
- }
+ // If we have an empty exit packet, lets fill one in to be safe.
+ if (!pid_exited_packet[0])
+ {
+ strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1);
+ pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0';
+ }
+
+ return SendPacket (pid_exited_packet);
+ }
break;
}
return rnb_success;
@@ -2244,6 +2226,10 @@ RNBRemote::HandlePacket_g (const char *p)
{
return SendPacket ("E11");
}
+
+ if (g_num_reg_entries == 0)
+ InitializeRegisters ();
+
nub_process_t pid = m_ctx.ProcessID ();
nub_thread_t tid = GetCurrentThread();
@@ -2283,6 +2269,10 @@ RNBRemote::HandlePacket_G (const char *p)
{
return SendPacket ("E11");
}
+
+ if (g_num_reg_entries == 0)
+ InitializeRegisters ();
+
StringExtractor packet(p);
packet.SetFilePos(1); // Skip the 'G'
@@ -2872,6 +2862,9 @@ RNBRemote::HandlePacket_z (const char *p)
rnb_err_t
RNBRemote::HandlePacket_p (const char *p)
{
+ if (g_num_reg_entries == 0)
+ InitializeRegisters ();
+
if (p == NULL || *p == '\0')
{
return HandlePacket_ILLFORMED ("No thread specified in p packet");
@@ -2931,6 +2924,9 @@ RNBRemote::HandlePacket_p (const char *p)
rnb_err_t
RNBRemote::HandlePacket_P (const char *p)
{
+ if (g_num_reg_entries == 0)
+ InitializeRegisters ();
+
if (p == NULL || *p == '\0')
{
return HandlePacket_ILLFORMED ("Empty P packet");
diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h
index 30ab7e67302..fab42bc9693 100644
--- a/lldb/tools/debugserver/source/RNBRemote.h
+++ b/lldb/tools/debugserver/source/RNBRemote.h
@@ -106,10 +106,12 @@ public:
typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p);
- RNBRemote(bool use_native_regs);
- ~RNBRemote();
+ RNBRemote (bool use_native_regs, const char *arch);
+ ~RNBRemote ();
- static void InitializeRegisters (int use_native);
+ void Initialize();
+
+ bool InitializeRegisters ();
rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL);
rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL);
@@ -194,9 +196,6 @@ private:
protected:
- static void
- InitializeNativeRegisters ();
-
rnb_err_t GetCommData ();
void CommDataReceived(const std::string& data);
struct Packet
@@ -273,8 +272,7 @@ protected:
typedef BreakpointMap::const_iterator BreakpointMapConstIter;
RNBContext m_ctx; // process context
RNBSocket m_comm; // communication port
- bool m_extended_mode; // are we in extended mode?
- bool m_noack_mode; // are we in no-ack mode?
+ std::string m_arch;
nub_thread_t m_continue_thread; // thread to continue; 0 for any, -1 for all
nub_thread_t m_thread; // thread for other ops; 0 for any, -1 for all
PThreadMutex m_mutex; // Mutex that protects
@@ -286,7 +284,9 @@ protected:
BreakpointMap m_breakpoints;
BreakpointMap m_watchpoints;
uint32_t m_max_payload_size; // the maximum sized payload we should send to gdb
- bool m_use_native_regs;
+ bool m_extended_mode:1, // are we in extended mode?
+ m_noack_mode:1, // are we in no-ack mode?
+ m_use_native_regs:1; // Use native registers by querying DNB layer for register definitions?
};
/* We translate the /usr/include/mach/exception_types.h exception types
diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp
index a3cae284d4f..e8c28cc5eae 100644
--- a/lldb/tools/debugserver/source/debugserver.cpp
+++ b/lldb/tools/debugserver/source/debugserver.cpp
@@ -334,7 +334,6 @@ RNBRunLoopLaunchAttaching (RNBRemoteSP &remote, nub_process_t attach_pid, nub_pr
}
else
{
-
ctx.SetProcessID(pid);
return eRNBRunLoopModeInferiorExecuting;
}
@@ -644,6 +643,7 @@ show_usage_and_exit (int exit_code)
static struct option g_long_options[] =
{
{ "attach", required_argument, NULL, 'a' },
+ { "arch", required_argument, NULL, 'A' },
{ "debug", no_argument, NULL, 'g' },
{ "verbose", no_argument, NULL, 'v' },
{ "lockdown", no_argument, &g_lockdown_opt, 1 }, // short option "-k"
@@ -695,6 +695,7 @@ main (int argc, char *argv[])
std::string waitfor_pid_name; // Wait for a process that starts with this name
std::string attach_pid_name;
std::string stdio_path;
+ std::string arch_name;
useconds_t waitfor_interval = 1000; // Time in usecs between process lists polls when waiting for a process by name, default 1 msec.
useconds_t waitfor_duration = 0; // Time in seconds to wait for a process by name, 0 means wait forever.
@@ -704,7 +705,7 @@ main (int argc, char *argv[])
RNBRunLoopMode start_mode = eRNBRunLoopModeExit;
- while ((ch = getopt_long(argc, argv, "a:d:gi:vktl:f:w:x:rs:", g_long_options, &long_option_index)) != -1)
+ while ((ch = getopt_long(argc, argv, "a:A:d:gi:vktl:f:w:x:rs:", g_long_options, &long_option_index)) != -1)
{
DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
ch, (uint8_t)ch,
@@ -716,6 +717,11 @@ main (int argc, char *argv[])
case 0: // Any optional that auto set themselves will return 0
break;
+ case 'A':
+ if (optarg && optarg[0])
+ arch_name.assign(optarg);
+ break;
+
case 'a':
if (optarg && optarg[0])
{
@@ -869,12 +875,28 @@ main (int argc, char *argv[])
break;
}
}
+
+ if (arch_name.empty())
+ {
+#if defined (__i386__)
+ arch_name.assign ("i386");
+#elif defined (__x86_64__)
+ arch_name.assign ("x86_64");
+#elif defined (__arm__)
+ arch_name.assign ("arm");
+#endif
+ }
+ if (arch_name.empty())
+ {
+ fprintf(stderr, "error: no architecture was specified\n");
+ exit (8);
+ }
// Skip any options we consumed with getopt_long
argc -= optind;
argv += optind;
- g_remoteSP.reset (new RNBRemote (use_native_registers));
+ g_remoteSP.reset (new RNBRemote (use_native_registers, arch_name.c_str()));
RNBRemote *remote = g_remoteSP.get();
if (remote == NULL)
@@ -883,6 +905,8 @@ main (int argc, char *argv[])
return -1;
}
+ g_remoteSP->Initialize();
+
RNBContext& ctx = remote->Context();
@@ -911,11 +935,6 @@ main (int argc, char *argv[])
DNBLogDebug("argv[%i] = %s", i, argv[i]);
}
- // Now that we have read in the options and enabled logging, initialize
- // the rest of RNBRemote
- RNBRemote::InitializeRegisters (use_native_registers);
-
-
// as long as we're dropping remotenub in as a replacement for gdbserver,
// explicitly note that this is not gdbserver.
OpenPOWER on IntegriCloud