Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 1 | //===-- POSIXThread.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 | |
Daniel Malea | d891f9b | 2012-12-05 00:20:57 +0000 | [diff] [blame] | 10 | #include "lldb/lldb-python.h" |
| 11 | |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 12 | // C Includes |
| 13 | #include <errno.h> |
| 14 | |
| 15 | // C++ Includes |
| 16 | // Other libraries and framework includes |
| 17 | // Project includes |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 18 | #include "lldb/Breakpoint/Watchpoint.h" |
Ashok Thirumurthi | 674f7d1 | 2013-07-12 19:19:15 +0000 | [diff] [blame] | 19 | #include "lldb/Breakpoint/BreakpointLocation.h" |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 20 | #include "lldb/Core/Debugger.h" |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 21 | #include "lldb/Core/State.h" |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 22 | #include "lldb/Host/Host.h" |
| 23 | #include "lldb/Target/Process.h" |
| 24 | #include "lldb/Target/StopInfo.h" |
| 25 | #include "lldb/Target/Target.h" |
Ashok Thirumurthi | 674f7d1 | 2013-07-12 19:19:15 +0000 | [diff] [blame] | 26 | #include "lldb/Target/ThreadSpec.h" |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 27 | #include "POSIXStopInfo.h" |
| 28 | #include "POSIXThread.h" |
| 29 | #include "ProcessPOSIX.h" |
| 30 | #include "ProcessPOSIXLog.h" |
| 31 | #include "ProcessMonitor.h" |
| 32 | #include "RegisterContext_i386.h" |
| 33 | #include "RegisterContext_x86_64.h" |
| 34 | #include "RegisterContextPOSIX.h" |
Ashok Thirumurthi | dae196d | 2013-05-01 20:17:59 +0000 | [diff] [blame] | 35 | #include "RegisterContextLinux_x86_64.h" |
| 36 | #include "RegisterContextFreeBSD_x86_64.h" |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 37 | |
| 38 | #include "UnwindLLDB.h" |
| 39 | |
Greg Clayton | e5eaa30 | 2012-02-21 18:40:07 +0000 | [diff] [blame] | 40 | using namespace lldb; |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 41 | using namespace lldb_private; |
| 42 | |
| 43 | |
Greg Clayton | 5e91e37 | 2012-10-12 16:23:23 +0000 | [diff] [blame] | 44 | POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 45 | : Thread(process, tid), |
Matt Kopec | 0ba7548 | 2013-07-10 20:53:11 +0000 | [diff] [blame] | 46 | m_frame_ap (), |
| 47 | m_breakpoint (), |
| 48 | m_thread_name () |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 49 | { |
Ashok Thirumurthi | d8f6b64 | 2013-03-28 16:02:31 +0000 | [diff] [blame] | 50 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 51 | if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) |
Daniel Malea | 5f35a4b | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 52 | log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid); |
Matt Kopec | 12c5bf3 | 2013-06-03 17:40:20 +0000 | [diff] [blame] | 53 | |
| 54 | // Set the current watchpoints for this thread. |
| 55 | Target &target = GetProcess()->GetTarget(); |
| 56 | const WatchpointList &wp_list = target.GetWatchpointList(); |
| 57 | size_t wp_size = wp_list.GetSize(); |
| 58 | |
| 59 | for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) |
| 60 | { |
| 61 | lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx); |
| 62 | if (wp.get() && wp->IsEnabled()) |
| 63 | { |
| 64 | assert(EnableHardwareWatchpoint(wp.get())); |
| 65 | } |
| 66 | } |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | POSIXThread::~POSIXThread() |
| 70 | { |
| 71 | DestroyThread(); |
| 72 | } |
| 73 | |
| 74 | ProcessMonitor & |
| 75 | POSIXThread::GetMonitor() |
| 76 | { |
Greg Clayton | e5eaa30 | 2012-02-21 18:40:07 +0000 | [diff] [blame] | 77 | ProcessSP base = GetProcess(); |
| 78 | ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 79 | return process.GetMonitor(); |
| 80 | } |
| 81 | |
| 82 | void |
| 83 | POSIXThread::RefreshStateAfterStop() |
| 84 | { |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 85 | // Invalidate all registers in our register context. We don't set "force" to |
| 86 | // true because the stop reply packet might have had some register values |
| 87 | // that were expedited and these will already be copied into the register |
| 88 | // context by the time this function gets called. The KDPRegisterContext |
| 89 | // class has been made smart enough to detect when it needs to invalidate |
| 90 | // which registers are valid by putting hooks in the register read and |
| 91 | // register supply functions where they check the process stop ID and do |
| 92 | // the right thing. |
| 93 | //if (StateIsStoppedState(GetState()) |
| 94 | { |
| 95 | const bool force = false; |
| 96 | GetRegisterContext()->InvalidateIfNeeded (force); |
| 97 | } |
| 98 | // FIXME: This should probably happen somewhere else. |
| 99 | SetResumeState(eStateRunning); |
Ashok Thirumurthi | d8f6b64 | 2013-03-28 16:02:31 +0000 | [diff] [blame] | 100 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 101 | if (log) |
| 102 | log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to running", __FUNCTION__, GetID()); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | const char * |
| 106 | POSIXThread::GetInfo() |
| 107 | { |
| 108 | return NULL; |
| 109 | } |
| 110 | |
Matt Kopec | 0ba7548 | 2013-07-10 20:53:11 +0000 | [diff] [blame] | 111 | void |
| 112 | POSIXThread::SetName (const char *name) |
| 113 | { |
| 114 | if (name && name[0]) |
| 115 | m_thread_name.assign (name); |
| 116 | else |
| 117 | m_thread_name.clear(); |
| 118 | } |
| 119 | |
| 120 | const char * |
| 121 | POSIXThread::GetName () |
| 122 | { |
| 123 | if (m_thread_name.empty()) |
| 124 | return NULL; |
| 125 | return m_thread_name.c_str(); |
| 126 | } |
| 127 | |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 128 | lldb::RegisterContextSP |
| 129 | POSIXThread::GetRegisterContext() |
| 130 | { |
| 131 | if (!m_reg_context_sp) |
| 132 | { |
| 133 | ArchSpec arch = Host::GetArchitecture(); |
| 134 | |
| 135 | switch (arch.GetCore()) |
| 136 | { |
| 137 | default: |
| 138 | assert(false && "CPU type not supported!"); |
| 139 | break; |
| 140 | |
| 141 | case ArchSpec::eCore_x86_32_i386: |
| 142 | case ArchSpec::eCore_x86_32_i486: |
| 143 | case ArchSpec::eCore_x86_32_i486sx: |
| 144 | m_reg_context_sp.reset(new RegisterContext_i386(*this, 0)); |
| 145 | break; |
| 146 | |
| 147 | case ArchSpec::eCore_x86_64_x86_64: |
Ed Maste | 8c2dc0e | 2013-07-30 14:40:59 +0000 | [diff] [blame^] | 148 | switch (arch.GetTriple().getOS()) |
| 149 | { |
| 150 | case llvm::Triple::FreeBSD: |
| 151 | m_reg_context_sp.reset(new RegisterContextFreeBSD_x86_64(*this, 0)); |
| 152 | break; |
| 153 | case llvm::Triple::Linux: |
| 154 | m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0)); |
| 155 | break; |
| 156 | default: |
| 157 | assert(false && "OS not supported"); |
| 158 | break; |
| 159 | } |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 160 | break; |
| 161 | } |
| 162 | } |
| 163 | return m_reg_context_sp; |
| 164 | } |
| 165 | |
| 166 | lldb::RegisterContextSP |
| 167 | POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) |
| 168 | { |
| 169 | lldb::RegisterContextSP reg_ctx_sp; |
| 170 | uint32_t concrete_frame_idx = 0; |
| 171 | |
Ashok Thirumurthi | d8f6b64 | 2013-03-28 16:02:31 +0000 | [diff] [blame] | 172 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 173 | if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) |
| 174 | log->Printf ("POSIXThread::%s ()", __FUNCTION__); |
| 175 | |
| 176 | if (frame) |
| 177 | concrete_frame_idx = frame->GetConcreteFrameIndex(); |
| 178 | |
| 179 | if (concrete_frame_idx == 0) |
| 180 | reg_ctx_sp = GetRegisterContext(); |
| 181 | else |
| 182 | { |
| 183 | assert(GetUnwinder()); |
| 184 | reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); |
| 185 | } |
| 186 | |
| 187 | return reg_ctx_sp; |
| 188 | } |
| 189 | |
Greg Clayton | 863aa28 | 2013-05-09 01:55:29 +0000 | [diff] [blame] | 190 | bool |
| 191 | POSIXThread::CalculateStopInfo() |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 192 | { |
Ashok Thirumurthi | dc07851 | 2013-05-09 13:58:54 +0000 | [diff] [blame] | 193 | SetStopInfo (m_stop_info_sp); |
Greg Clayton | 863aa28 | 2013-05-09 01:55:29 +0000 | [diff] [blame] | 194 | return true; |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | Unwind * |
| 198 | POSIXThread::GetUnwinder() |
| 199 | { |
| 200 | if (m_unwinder_ap.get() == NULL) |
| 201 | m_unwinder_ap.reset(new UnwindLLDB(*this)); |
| 202 | |
| 203 | return m_unwinder_ap.get(); |
| 204 | } |
| 205 | |
Greg Clayton | a46013b | 2013-05-01 21:54:04 +0000 | [diff] [blame] | 206 | void |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 207 | POSIXThread::WillResume(lldb::StateType resume_state) |
| 208 | { |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 209 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); |
| 210 | if (log) |
| 211 | log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to %s", __FUNCTION__, GetID(), StateAsCString(resume_state)); |
| 212 | // TODO: the line below shouldn't really be done, but |
Greg Clayton | a46013b | 2013-05-01 21:54:04 +0000 | [diff] [blame] | 213 | // the POSIXThread might rely on this so I will leave this in for now |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 214 | SetResumeState(resume_state); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 215 | } |
| 216 | |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 217 | void |
| 218 | POSIXThread::DidStop() |
| 219 | { |
| 220 | // Don't set the thread state to stopped unless we really stopped. |
| 221 | } |
| 222 | |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 223 | bool |
| 224 | POSIXThread::Resume() |
| 225 | { |
| 226 | lldb::StateType resume_state = GetResumeState(); |
| 227 | ProcessMonitor &monitor = GetMonitor(); |
| 228 | bool status; |
| 229 | |
Ashok Thirumurthi | d8f6b64 | 2013-03-28 16:02:31 +0000 | [diff] [blame] | 230 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 231 | if (log) |
| 232 | log->Printf ("POSIXThread::%s (), resume_state = %s", __FUNCTION__, |
| 233 | StateAsCString(resume_state)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 234 | |
| 235 | switch (resume_state) |
| 236 | { |
| 237 | default: |
| 238 | assert(false && "Unexpected state for resume!"); |
| 239 | status = false; |
| 240 | break; |
| 241 | |
| 242 | case lldb::eStateRunning: |
| 243 | SetState(resume_state); |
| 244 | status = monitor.Resume(GetID(), GetResumeSignal()); |
| 245 | break; |
| 246 | |
| 247 | case lldb::eStateStepping: |
| 248 | SetState(resume_state); |
| 249 | status = monitor.SingleStep(GetID(), GetResumeSignal()); |
| 250 | break; |
Daniel Malea | d601e83 | 2013-02-13 22:00:44 +0000 | [diff] [blame] | 251 | case lldb::eStateStopped: |
| 252 | case lldb::eStateSuspended: |
| 253 | status = true; |
| 254 | break; |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 255 | } |
| 256 | |
| 257 | return status; |
| 258 | } |
| 259 | |
| 260 | void |
| 261 | POSIXThread::Notify(const ProcessMessage &message) |
| 262 | { |
Ashok Thirumurthi | d8f6b64 | 2013-03-28 16:02:31 +0000 | [diff] [blame] | 263 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 264 | if (log) |
Matt Kopec | 010a8d8 | 2013-06-10 22:14:47 +0000 | [diff] [blame] | 265 | log->Printf ("POSIXThread::%s () message kind = '%s' for tid %" PRIu64, |
| 266 | __FUNCTION__, message.PrintKind(), GetID()); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 267 | |
| 268 | switch (message.GetKind()) |
| 269 | { |
| 270 | default: |
| 271 | assert(false && "Unexpected message kind!"); |
| 272 | break; |
| 273 | |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 274 | case ProcessMessage::eExitMessage: |
| 275 | // Nothing to be done. |
| 276 | break; |
| 277 | |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 278 | case ProcessMessage::eLimboMessage: |
| 279 | LimboNotify(message); |
| 280 | break; |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 281 | |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 282 | case ProcessMessage::eSignalMessage: |
| 283 | SignalNotify(message); |
| 284 | break; |
| 285 | |
| 286 | case ProcessMessage::eSignalDeliveredMessage: |
| 287 | SignalDeliveredNotify(message); |
| 288 | break; |
| 289 | |
| 290 | case ProcessMessage::eTraceMessage: |
| 291 | TraceNotify(message); |
| 292 | break; |
| 293 | |
| 294 | case ProcessMessage::eBreakpointMessage: |
| 295 | BreakNotify(message); |
| 296 | break; |
| 297 | |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 298 | case ProcessMessage::eWatchpointMessage: |
| 299 | WatchNotify(message); |
| 300 | break; |
| 301 | |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 302 | case ProcessMessage::eCrashMessage: |
| 303 | CrashNotify(message); |
| 304 | break; |
Matt Kopec | f1fda37 | 2013-01-08 16:30:18 +0000 | [diff] [blame] | 305 | |
| 306 | case ProcessMessage::eNewThreadMessage: |
| 307 | ThreadNotify(message); |
| 308 | break; |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 309 | } |
| 310 | } |
| 311 | |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 312 | bool |
| 313 | POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp) |
| 314 | { |
Matt Kopec | 12c5bf3 | 2013-06-03 17:40:20 +0000 | [diff] [blame] | 315 | bool wp_set = false; |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 316 | if (wp) |
| 317 | { |
| 318 | addr_t wp_addr = wp->GetLoadAddress(); |
| 319 | size_t wp_size = wp->GetByteSize(); |
| 320 | bool wp_read = wp->WatchpointRead(); |
| 321 | bool wp_write = wp->WatchpointWrite(); |
Matt Kopec | 12c5bf3 | 2013-06-03 17:40:20 +0000 | [diff] [blame] | 322 | uint32_t wp_hw_index = wp->GetHardwareIndex(); |
| 323 | RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX(); |
| 324 | if (reg_ctx) |
| 325 | wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size, |
| 326 | wp_read, wp_write, |
| 327 | wp_hw_index); |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 328 | } |
Matt Kopec | 12c5bf3 | 2013-06-03 17:40:20 +0000 | [diff] [blame] | 329 | return wp_set; |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 330 | } |
| 331 | |
| 332 | bool |
| 333 | POSIXThread::DisableHardwareWatchpoint(Watchpoint *wp) |
| 334 | { |
| 335 | bool result = false; |
| 336 | if (wp) |
| 337 | { |
| 338 | lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); |
| 339 | if (reg_ctx_sp.get()) |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 340 | result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex()); |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 341 | } |
| 342 | return result; |
| 343 | } |
| 344 | |
| 345 | uint32_t |
| 346 | POSIXThread::NumSupportedHardwareWatchpoints() |
| 347 | { |
| 348 | lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); |
| 349 | if (reg_ctx_sp.get()) |
| 350 | return reg_ctx_sp->NumSupportedHardwareWatchpoints(); |
| 351 | return 0; |
| 352 | } |
| 353 | |
Matt Kopec | 12c5bf3 | 2013-06-03 17:40:20 +0000 | [diff] [blame] | 354 | uint32_t |
| 355 | POSIXThread::FindVacantWatchpointIndex() |
| 356 | { |
| 357 | uint32_t hw_index = LLDB_INVALID_INDEX32; |
| 358 | uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); |
| 359 | uint32_t wp_idx; |
| 360 | RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX(); |
| 361 | if (reg_ctx) |
| 362 | { |
| 363 | for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) |
| 364 | { |
| 365 | if (reg_ctx->IsWatchpointVacant(wp_idx)) |
| 366 | { |
| 367 | hw_index = wp_idx; |
| 368 | break; |
| 369 | } |
| 370 | } |
| 371 | } |
| 372 | return hw_index; |
| 373 | } |
| 374 | |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 375 | void |
| 376 | POSIXThread::BreakNotify(const ProcessMessage &message) |
| 377 | { |
| 378 | bool status; |
Ashok Thirumurthi | d8f6b64 | 2013-03-28 16:02:31 +0000 | [diff] [blame] | 379 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 380 | |
| 381 | assert(GetRegisterContext()); |
| 382 | status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint(); |
| 383 | assert(status && "Breakpoint update failed!"); |
| 384 | |
| 385 | // With our register state restored, resolve the breakpoint object |
| 386 | // corresponding to our current PC. |
| 387 | assert(GetRegisterContext()); |
| 388 | lldb::addr_t pc = GetRegisterContext()->GetPC(); |
| 389 | if (log) |
Daniel Malea | 5f35a4b | 2012-11-29 21:49:15 +0000 | [diff] [blame] | 390 | log->Printf ("POSIXThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); |
Greg Clayton | e5eaa30 | 2012-02-21 18:40:07 +0000 | [diff] [blame] | 391 | lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 392 | |
Ashok Thirumurthi | 674f7d1 | 2013-07-12 19:19:15 +0000 | [diff] [blame] | 393 | // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, |
| 394 | // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that |
| 395 | // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. |
| 396 | if (bp_site && bp_site->ValidForThisThread(this)) |
| 397 | { |
| 398 | lldb::break_id_t bp_id = bp_site->GetID(); |
| 399 | if (GetProcess()->GetThreadList().SetSelectedThreadByID(GetID())) |
| 400 | SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id)); |
| 401 | else |
| 402 | assert(false && "Invalid thread ID during BreakNotify."); |
| 403 | } |
| 404 | else |
| 405 | { |
| 406 | const ThreadSpec *spec = bp_site ? |
| 407 | bp_site->GetOwnerAtIndex(0)->GetOptionsNoCreate()->GetThreadSpecNoCreate() : 0; |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 408 | |
Ashok Thirumurthi | 674f7d1 | 2013-07-12 19:19:15 +0000 | [diff] [blame] | 409 | if (spec && spec->TIDMatches(*this)) |
| 410 | assert(false && "BreakpointSite is invalid for the current ThreadSpec."); |
| 411 | else |
| 412 | { |
| 413 | if (!m_stop_info_sp) { |
| 414 | StopInfoSP invalid_stop_info_sp; |
| 415 | SetStopInfo (invalid_stop_info_sp); |
| 416 | } |
| 417 | } |
| 418 | } |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 419 | } |
| 420 | |
| 421 | void |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 422 | POSIXThread::WatchNotify(const ProcessMessage &message) |
| 423 | { |
| 424 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); |
| 425 | |
| 426 | lldb::addr_t halt_addr = message.GetHWAddress(); |
| 427 | if (log) |
| 428 | log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8" |
| 429 | PRIx64, __FUNCTION__, halt_addr); |
| 430 | |
| 431 | RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX(); |
| 432 | if (reg_ctx) |
| 433 | { |
| 434 | uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); |
| 435 | uint32_t wp_idx; |
| 436 | for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) |
| 437 | { |
| 438 | if (reg_ctx->IsWatchpointHit(wp_idx)) |
| 439 | { |
| 440 | // Clear the watchpoint hit here |
| 441 | reg_ctx->ClearWatchpointHits(); |
| 442 | break; |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | if (wp_idx == num_hw_wps) |
| 447 | return; |
| 448 | |
| 449 | Target &target = GetProcess()->GetTarget(); |
| 450 | lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx); |
| 451 | const WatchpointList &wp_list = target.GetWatchpointList(); |
| 452 | lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr); |
| 453 | |
Matt Kopec | aeb2faf | 2013-06-18 21:58:02 +0000 | [diff] [blame] | 454 | assert(wp_sp.get() && "No watchpoint found"); |
| 455 | SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this, |
| 456 | wp_sp->GetID())); |
Matt Kopec | 3d4d51c | 2013-05-07 19:29:28 +0000 | [diff] [blame] | 457 | } |
| 458 | } |
| 459 | |
| 460 | void |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 461 | POSIXThread::TraceNotify(const ProcessMessage &message) |
| 462 | { |
Matt Kopec | 6a988f4 | 2013-06-18 21:35:32 +0000 | [diff] [blame] | 463 | #ifndef __FreeBSD__ |
Matt Kopec | a7c0f9f | 2013-05-08 16:10:09 +0000 | [diff] [blame] | 464 | RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX(); |
| 465 | if (reg_ctx) |
| 466 | { |
| 467 | uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); |
| 468 | uint32_t wp_idx; |
| 469 | for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) |
| 470 | { |
| 471 | if (reg_ctx->IsWatchpointHit(wp_idx)) |
| 472 | { |
| 473 | WatchNotify(message); |
| 474 | return; |
| 475 | } |
| 476 | } |
| 477 | } |
Matt Kopec | 6a988f4 | 2013-06-18 21:35:32 +0000 | [diff] [blame] | 478 | #endif |
Andrew Kaylor | 4e75e35 | 2013-05-07 18:35:34 +0000 | [diff] [blame] | 479 | SetStopInfo (StopInfo::CreateStopReasonToTrace(*this)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 480 | } |
| 481 | |
| 482 | void |
| 483 | POSIXThread::LimboNotify(const ProcessMessage &message) |
| 484 | { |
Andrew Kaylor | 4e75e35 | 2013-05-07 18:35:34 +0000 | [diff] [blame] | 485 | SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this))); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 486 | } |
| 487 | |
| 488 | void |
| 489 | POSIXThread::SignalNotify(const ProcessMessage &message) |
| 490 | { |
| 491 | int signo = message.GetSignal(); |
| 492 | |
Andrew Kaylor | 4e75e35 | 2013-05-07 18:35:34 +0000 | [diff] [blame] | 493 | SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 494 | SetResumeSignal(signo); |
| 495 | } |
| 496 | |
| 497 | void |
| 498 | POSIXThread::SignalDeliveredNotify(const ProcessMessage &message) |
| 499 | { |
| 500 | int signo = message.GetSignal(); |
| 501 | |
Andrew Kaylor | 4e75e35 | 2013-05-07 18:35:34 +0000 | [diff] [blame] | 502 | SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 503 | SetResumeSignal(signo); |
| 504 | } |
| 505 | |
| 506 | void |
| 507 | POSIXThread::CrashNotify(const ProcessMessage &message) |
| 508 | { |
Andrew Kaylor | 3bd2ebd | 2013-05-28 23:04:25 +0000 | [diff] [blame] | 509 | // FIXME: Update stop reason as per bugzilla 14598 |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 510 | int signo = message.GetSignal(); |
| 511 | |
| 512 | assert(message.GetKind() == ProcessMessage::eCrashMessage); |
| 513 | |
Ashok Thirumurthi | d8f6b64 | 2013-03-28 16:02:31 +0000 | [diff] [blame] | 514 | Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 515 | if (log) |
Matt Kopec | 010a8d8 | 2013-06-10 22:14:47 +0000 | [diff] [blame] | 516 | log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", |
| 517 | __FUNCTION__, signo, message.PrintCrashReason()); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 518 | |
Matt Kopec | 010a8d8 | 2013-06-10 22:14:47 +0000 | [diff] [blame] | 519 | SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo, |
| 520 | message.GetCrashReason(), |
| 521 | message.GetFaultAddress()))); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 522 | SetResumeSignal(signo); |
| 523 | } |
| 524 | |
Matt Kopec | f1fda37 | 2013-01-08 16:30:18 +0000 | [diff] [blame] | 525 | void |
| 526 | POSIXThread::ThreadNotify(const ProcessMessage &message) |
| 527 | { |
Andrew Kaylor | 4e75e35 | 2013-05-07 18:35:34 +0000 | [diff] [blame] | 528 | SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this))); |
Matt Kopec | f1fda37 | 2013-01-08 16:30:18 +0000 | [diff] [blame] | 529 | } |
| 530 | |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 531 | unsigned |
| 532 | POSIXThread::GetRegisterIndexFromOffset(unsigned offset) |
| 533 | { |
Andy Gibbs | 3a0e6a5 | 2013-06-19 20:04:56 +0000 | [diff] [blame] | 534 | unsigned reg = LLDB_INVALID_REGNUM; |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 535 | ArchSpec arch = Host::GetArchitecture(); |
| 536 | |
| 537 | switch (arch.GetCore()) |
| 538 | { |
| 539 | default: |
Andy Gibbs | 09dffd8 | 2013-06-19 19:05:52 +0000 | [diff] [blame] | 540 | llvm_unreachable("CPU type not supported!"); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 541 | break; |
| 542 | |
| 543 | case ArchSpec::eCore_x86_32_i386: |
| 544 | case ArchSpec::eCore_x86_32_i486: |
| 545 | case ArchSpec::eCore_x86_32_i486sx: |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 546 | case ArchSpec::eCore_x86_64_x86_64: |
Ashok Thirumurthi | c73fedb | 2013-05-09 19:59:47 +0000 | [diff] [blame] | 547 | { |
| 548 | RegisterContextSP base = GetRegisterContext(); |
| 549 | if (base) { |
| 550 | RegisterContextPOSIX &context = static_cast<RegisterContextPOSIX &>(*base); |
| 551 | reg = context.GetRegisterIndexFromOffset(offset); |
| 552 | } |
| 553 | } |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 554 | break; |
| 555 | } |
| 556 | return reg; |
| 557 | } |
| 558 | |
| 559 | const char * |
| 560 | POSIXThread::GetRegisterName(unsigned reg) |
| 561 | { |
Ashok Thirumurthi | c73fedb | 2013-05-09 19:59:47 +0000 | [diff] [blame] | 562 | const char * name = nullptr; |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 563 | ArchSpec arch = Host::GetArchitecture(); |
| 564 | |
| 565 | switch (arch.GetCore()) |
| 566 | { |
| 567 | default: |
| 568 | assert(false && "CPU type not supported!"); |
| 569 | break; |
| 570 | |
| 571 | case ArchSpec::eCore_x86_32_i386: |
| 572 | case ArchSpec::eCore_x86_32_i486: |
| 573 | case ArchSpec::eCore_x86_32_i486sx: |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 574 | case ArchSpec::eCore_x86_64_x86_64: |
Ashok Thirumurthi | c73fedb | 2013-05-09 19:59:47 +0000 | [diff] [blame] | 575 | name = GetRegisterContext()->GetRegisterName(reg); |
Johnny Chen | 2341d35 | 2012-01-05 21:48:15 +0000 | [diff] [blame] | 576 | break; |
| 577 | } |
| 578 | return name; |
| 579 | } |
| 580 | |
| 581 | const char * |
| 582 | POSIXThread::GetRegisterNameFromOffset(unsigned offset) |
| 583 | { |
| 584 | return GetRegisterName(GetRegisterIndexFromOffset(offset)); |
| 585 | } |
| 586 | |