1 //===-- ProcessLinux.cpp ----------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 #include <errno.h> 12 13 // C++ Includes 14 // Other libraries and framework includes 15 #include "lldb/Core/PluginManager.h" 16 #include "lldb/Core/State.h" 17 #include "lldb/Host/Host.h" 18 #include "lldb/Symbol/ObjectFile.h" 19 #include "lldb/Target/DynamicLoader.h" 20 #include "lldb/Target/Target.h" 21 22 #include "ProcessLinux.h" 23 #include "ProcessPOSIXLog.h" 24 #include "Plugins/Process/Utility/InferiorCallPOSIX.h" 25 #include "ProcessMonitor.h" 26 #include "LinuxThread.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 //------------------------------------------------------------------------------ 32 // Static functions. 33 34 ProcessSP 35 ProcessLinux::CreateInstance(Target &target, Listener &listener, const FileSpec *core_file) 36 { 37 return ProcessSP(new ProcessLinux(target, listener, (FileSpec *)core_file)); 38 } 39 40 void 41 ProcessLinux::Initialize() 42 { 43 static bool g_initialized = false; 44 45 if (!g_initialized) 46 { 47 g_initialized = true; 48 PluginManager::RegisterPlugin(GetPluginNameStatic(), 49 GetPluginDescriptionStatic(), 50 CreateInstance); 51 52 Log::Callbacks log_callbacks = { 53 ProcessPOSIXLog::DisableLog, 54 ProcessPOSIXLog::EnableLog, 55 ProcessPOSIXLog::ListLogCategories 56 }; 57 58 Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks); 59 ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); 60 } 61 } 62 63 //------------------------------------------------------------------------------ 64 // Constructors and destructors. 65 66 ProcessLinux::ProcessLinux(Target& target, Listener &listener, FileSpec *core_file) 67 : ProcessPOSIX(target, listener), m_core_file(core_file), m_stopping_threads(false) 68 { 69 #if 0 70 // FIXME: Putting this code in the ctor and saving the byte order in a 71 // member variable is a hack to avoid const qual issues in GetByteOrder. 72 ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); 73 m_byte_order = obj_file->GetByteOrder(); 74 #else 75 // XXX: Will work only for local processes. 76 m_byte_order = lldb::endian::InlHostByteOrder(); 77 #endif 78 } 79 80 void 81 ProcessLinux::Terminate() 82 { 83 } 84 85 lldb_private::ConstString 86 ProcessLinux::GetPluginNameStatic() 87 { 88 static ConstString g_name("linux"); 89 return g_name; 90 } 91 92 const char * 93 ProcessLinux::GetPluginDescriptionStatic() 94 { 95 return "Process plugin for Linux"; 96 } 97 98 99 bool 100 ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) 101 { 102 new_thread_list = old_thread_list; 103 return new_thread_list.GetSize(false) > 0; 104 } 105 106 107 //------------------------------------------------------------------------------ 108 // ProcessInterface protocol. 109 110 lldb_private::ConstString 111 ProcessLinux::GetPluginName() 112 { 113 return GetPluginNameStatic(); 114 } 115 116 uint32_t 117 ProcessLinux::GetPluginVersion() 118 { 119 return 1; 120 } 121 122 void 123 ProcessLinux::GetPluginCommandHelp(const char *command, Stream *strm) 124 { 125 } 126 127 Error 128 ProcessLinux::ExecutePluginCommand(Args &command, Stream *strm) 129 { 130 return Error(1, eErrorTypeGeneric); 131 } 132 133 Log * 134 ProcessLinux::EnablePluginLogging(Stream *strm, Args &command) 135 { 136 return NULL; 137 } 138 139 // ProcessPOSIX override 140 void 141 ProcessLinux::StopAllThreads(lldb::tid_t stop_tid) 142 { 143 // If a breakpoint occurs while we're stopping threads, we'll get back 144 // here, but we don't want to do it again. Only the MonitorChildProcess 145 // thread calls this function, so we don't need to protect this flag. 146 if (m_stopping_threads) 147 return; 148 m_stopping_threads = true; 149 150 Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); 151 if (log) 152 log->Printf ("ProcessLinux::%s() stopping all threads", __FUNCTION__); 153 154 // Walk the thread list and stop the other threads. The thread that caused 155 // the stop should already be marked as stopped before we get here. 156 Mutex::Locker thread_list_lock(m_thread_list.GetMutex()); 157 158 uint32_t thread_count = m_thread_list.GetSize(false); 159 for (uint32_t i = 0; i < thread_count; ++i) 160 { 161 POSIXThread *thread = static_cast<POSIXThread*>( 162 m_thread_list.GetThreadAtIndex(i, false).get()); 163 assert(thread); 164 lldb::tid_t tid = thread->GetID(); 165 if (!StateIsStoppedState(thread->GetState(), false)) 166 m_monitor->StopThread(tid); 167 } 168 169 m_stopping_threads = false; 170 171 if (log) 172 log->Printf ("ProcessLinux::%s() finished", __FUNCTION__); 173 } 174 175 // ProcessPOSIX override 176 POSIXThread * 177 ProcessLinux::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid) 178 { 179 return new LinuxThread(process, tid); 180 } 181 182 bool 183 ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name) 184 { 185 if (plugin_specified_by_name) 186 return true; 187 188 /* If core file is specified then let elf-core plugin handle it */ 189 if (m_core_file) 190 return false; 191 192 return ProcessPOSIX::CanDebug(target, plugin_specified_by_name); 193 } 194 195