1 //===-- ProcessMessage.h ----------------------------------------*- 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 #ifndef liblldb_ProcessMessage_H_
11 #define liblldb_ProcessMessage_H_
12 
13 #include "CrashReason.h"
14 
15 #include <cassert>
16 #include <string>
17 
18 #include "lldb/lldb-defines.h"
19 #include "lldb/lldb-types.h"
20 
21 class ProcessMessage {
22 public:
23   /// The type of signal this message can correspond to.
24   enum Kind {
25     eInvalidMessage,
26     eAttachMessage,
27     eExitMessage,
28     eLimboMessage,
29     eSignalMessage,
30     eSignalDeliveredMessage,
31     eTraceMessage,
32     eBreakpointMessage,
33     eWatchpointMessage,
34     eCrashMessage,
35     eNewThreadMessage,
36     eExecMessage
37   };
38 
39   ProcessMessage()
40       : m_tid(LLDB_INVALID_PROCESS_ID), m_kind(eInvalidMessage),
41         m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0),
42         m_addr(0) {}
43 
44   Kind GetKind() const { return m_kind; }
45 
46   lldb::tid_t GetTID() const { return m_tid; }
47 
48   /// Indicates that the process @p pid has successfully attached.
49   static ProcessMessage Attach(lldb::pid_t pid) {
50     return ProcessMessage(pid, eAttachMessage);
51   }
52 
53   /// Indicates that the thread @p tid is about to exit with status @p status.
54   static ProcessMessage Limbo(lldb::tid_t tid, int status) {
55     return ProcessMessage(tid, eLimboMessage, status);
56   }
57 
58   /// Indicates that the thread @p tid had the signal @p signum delivered.
59   static ProcessMessage Signal(lldb::tid_t tid, int signum) {
60     return ProcessMessage(tid, eSignalMessage, signum);
61   }
62 
63   /// Indicates that a signal @p signum generated by the debugging process was
64   /// delivered to the thread @p tid.
65   static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) {
66     return ProcessMessage(tid, eSignalDeliveredMessage, signum);
67   }
68 
69   /// Indicates that the thread @p tid encountered a trace point.
70   static ProcessMessage Trace(lldb::tid_t tid) {
71     return ProcessMessage(tid, eTraceMessage);
72   }
73 
74   /// Indicates that the thread @p tid encountered a break point.
75   static ProcessMessage Break(lldb::tid_t tid) {
76     return ProcessMessage(tid, eBreakpointMessage);
77   }
78 
79   static ProcessMessage Watch(lldb::tid_t tid, lldb::addr_t wp_addr) {
80     return ProcessMessage(tid, eWatchpointMessage, 0, wp_addr);
81   }
82 
83   /// Indicates that the thread @p tid crashed.
84   static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, int signo,
85                               lldb::addr_t fault_addr) {
86     ProcessMessage message(pid, eCrashMessage, signo, fault_addr);
87     message.m_crash_reason = reason;
88     return message;
89   }
90 
91   /// Indicates that the thread @p child_tid was spawned.
92   static ProcessMessage NewThread(lldb::tid_t parent_tid,
93                                   lldb::tid_t child_tid) {
94     return ProcessMessage(parent_tid, eNewThreadMessage, child_tid);
95   }
96 
97   /// Indicates that the thread @p tid is about to exit with status @p status.
98   static ProcessMessage Exit(lldb::tid_t tid, int status) {
99     return ProcessMessage(tid, eExitMessage, status);
100   }
101 
102   /// Indicates that the thread @p pid has exec'd.
103   static ProcessMessage Exec(lldb::tid_t tid) {
104     return ProcessMessage(tid, eExecMessage);
105   }
106 
107   int GetExitStatus() const {
108     assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);
109     return m_status;
110   }
111 
112   int GetSignal() const {
113     assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage ||
114            GetKind() == eSignalDeliveredMessage);
115     return m_status;
116   }
117 
118   int GetStopStatus() const {
119     assert(GetKind() == eSignalMessage);
120     return m_status;
121   }
122 
123   CrashReason GetCrashReason() const {
124     assert(GetKind() == eCrashMessage);
125     return m_crash_reason;
126   }
127 
128   lldb::addr_t GetFaultAddress() const {
129     assert(GetKind() == eCrashMessage);
130     return m_addr;
131   }
132 
133   lldb::addr_t GetHWAddress() const {
134     assert(GetKind() == eWatchpointMessage || GetKind() == eTraceMessage);
135     return m_addr;
136   }
137 
138   lldb::tid_t GetChildTID() const {
139     assert(GetKind() == eNewThreadMessage);
140     return m_child_tid;
141   }
142 
143   const char *PrintCrashReason() const;
144 
145   const char *PrintKind() const;
146 
147   static const char *PrintKind(Kind);
148 
149 private:
150   ProcessMessage(lldb::tid_t tid, Kind kind, int status = 0,
151                  lldb::addr_t addr = 0)
152       : m_tid(tid), m_kind(kind),
153         m_crash_reason(CrashReason::eInvalidCrashReason), m_status(status),
154         m_addr(addr), m_child_tid(0) {}
155 
156   ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid)
157       : m_tid(tid), m_kind(kind),
158         m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0),
159         m_addr(0), m_child_tid(child_tid) {}
160 
161   lldb::tid_t m_tid;
162   Kind m_kind : 8;
163   CrashReason m_crash_reason;
164   int m_status;
165   lldb::addr_t m_addr;
166   lldb::tid_t m_child_tid;
167 };
168 
169 #endif // #ifndef liblldb_ProcessMessage_H_
170