1 //===-- StopInfoMachException.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 #include "StopInfoMachException.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/ArchSpec.h" 17 #include "lldb/Core/StreamString.h" 18 #include "lldb/Target/Process.h" 19 #include "lldb/Target/RegisterContext.h" 20 #include "lldb/Target/Target.h" 21 #include "lldb/Target/Thread.h" 22 #include "lldb/Target/ThreadPlan.h" 23 #include "lldb/Target/UnixSignals.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 const char * 29 StopInfoMachException::GetDescription () 30 { 31 if (m_description.empty() && m_value != 0) 32 { 33 ArchSpec::CPU cpu = m_thread.GetProcess().GetTarget().GetArchitecture().GetGenericCPUType(); 34 35 const char *exc_desc = NULL; 36 const char *code_label = "code"; 37 const char *code_desc = NULL; 38 const char *subcode_label = "subcode"; 39 const char *subcode_desc = NULL; 40 switch (m_value) 41 { 42 case 1: // EXC_BAD_ACCESS 43 exc_desc = "EXC_BAD_ACCESS"; 44 subcode_label = "address"; 45 switch (cpu) 46 { 47 case ArchSpec::eCPU_arm: 48 switch (m_exc_code) 49 { 50 case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; 51 case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; 52 } 53 break; 54 55 case ArchSpec::eCPU_ppc: 56 case ArchSpec::eCPU_ppc64: 57 switch (m_exc_code) 58 { 59 case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break; 60 case 0x102: code_desc = "EXC_PPC_BADSPACE"; break; 61 case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break; 62 } 63 break; 64 65 default: 66 break; 67 } 68 break; 69 70 case 2: // EXC_BAD_INSTRUCTION 71 exc_desc = "EXC_BAD_INSTRUCTION"; 72 switch (cpu) 73 { 74 case ArchSpec::eCPU_i386: 75 case ArchSpec::eCPU_x86_64: 76 if (m_exc_code == 1) 77 code_desc = "EXC_I386_INVOP"; 78 break; 79 80 case ArchSpec::eCPU_ppc: 81 case ArchSpec::eCPU_ppc64: 82 switch (m_exc_code) 83 { 84 case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break; 85 case 2: code_desc = "EXC_PPC_UNIPL_INST"; break; 86 case 3: code_desc = "EXC_PPC_PRIVINST"; break; 87 case 4: code_desc = "EXC_PPC_PRIVREG"; break; 88 case 5: code_desc = "EXC_PPC_TRACE"; break; 89 case 6: code_desc = "EXC_PPC_PERFMON"; break; 90 } 91 break; 92 93 case ArchSpec::eCPU_arm: 94 if (m_exc_code == 1) 95 code_desc = "EXC_ARM_UNDEFINED"; 96 break; 97 98 default: 99 break; 100 } 101 break; 102 103 case 3: // EXC_ARITHMETIC 104 exc_desc = "EXC_ARITHMETIC"; 105 switch (cpu) 106 { 107 case ArchSpec::eCPU_i386: 108 case ArchSpec::eCPU_x86_64: 109 switch (m_exc_code) 110 { 111 case 1: code_desc = "EXC_I386_DIV"; break; 112 case 2: code_desc = "EXC_I386_INTO"; break; 113 case 3: code_desc = "EXC_I386_NOEXT"; break; 114 case 4: code_desc = "EXC_I386_EXTOVR"; break; 115 case 5: code_desc = "EXC_I386_EXTERR"; break; 116 case 6: code_desc = "EXC_I386_EMERR"; break; 117 case 7: code_desc = "EXC_I386_BOUND"; break; 118 case 8: code_desc = "EXC_I386_SSEEXTERR"; break; 119 } 120 break; 121 122 case ArchSpec::eCPU_ppc: 123 case ArchSpec::eCPU_ppc64: 124 switch (m_exc_code) 125 { 126 case 1: code_desc = "EXC_PPC_OVERFLOW"; break; 127 case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break; 128 case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break; 129 case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break; 130 case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break; 131 case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break; 132 case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break; 133 } 134 break; 135 136 default: 137 break; 138 } 139 break; 140 141 case 4: // EXC_EMULATION 142 exc_desc = "EXC_EMULATION"; 143 break; 144 145 146 case 5: // EXC_SOFTWARE 147 exc_desc = "EXC_SOFTWARE"; 148 if (m_exc_code == 0x10003) 149 { 150 subcode_desc = "EXC_SOFT_SIGNAL"; 151 subcode_label = "signo"; 152 } 153 break; 154 155 case 6: // EXC_BREAKPOINT 156 { 157 exc_desc = "EXC_BREAKPOINT"; 158 switch (cpu) 159 { 160 case ArchSpec::eCPU_i386: 161 case ArchSpec::eCPU_x86_64: 162 switch (m_exc_code) 163 { 164 case 1: subcode_desc = "EXC_I386_SGL"; break; 165 case 2: subcode_desc = "EXC_I386_BPT"; break; 166 } 167 break; 168 169 case ArchSpec::eCPU_ppc: 170 case ArchSpec::eCPU_ppc64: 171 switch (m_exc_code) 172 { 173 case 1: subcode_desc = "EXC_PPC_BREAKPOINT"; break; 174 } 175 break; 176 177 case ArchSpec::eCPU_arm: 178 switch (m_exc_code) 179 { 180 case 1: subcode_desc = "EXC_ARM_BREAKPOINT"; break; 181 } 182 break; 183 184 default: 185 break; 186 } 187 } 188 break; 189 190 case 7: 191 exc_desc = "EXC_SYSCALL"; 192 break; 193 194 case 8: 195 exc_desc = "EXC_MACH_SYSCALL"; 196 break; 197 198 case 9: 199 exc_desc = "EXC_RPC_ALERT"; 200 break; 201 202 case 10: 203 exc_desc = "EXC_CRASH"; 204 break; 205 } 206 207 StreamString strm; 208 209 if (exc_desc) 210 strm.PutCString(exc_desc); 211 else 212 strm.Printf("EXC_??? (%llu)", m_value); 213 214 if (m_exc_data_count >= 1) 215 { 216 if (code_desc) 217 strm.Printf(" (%s=%s", code_label, code_desc); 218 else 219 strm.Printf(" (%s=%llu", code_label, m_exc_code); 220 } 221 222 if (m_exc_data_count >= 2) 223 { 224 if (subcode_desc) 225 strm.Printf(", %s=%s", subcode_label, subcode_desc); 226 else 227 strm.Printf(", %s=0x%llx", subcode_label, m_exc_subcode); 228 } 229 230 if (m_exc_data_count > 0) 231 strm.PutChar(')'); 232 233 m_description.swap (strm.GetString()); 234 } 235 return m_description.c_str(); 236 } 237 238 239 StopInfoSP 240 StopInfoMachException::CreateStopReasonWithMachException 241 ( 242 Thread &thread, 243 uint32_t exc_type, 244 uint32_t exc_data_count, 245 uint64_t exc_code, 246 uint64_t exc_sub_code 247 ) 248 { 249 if (exc_type != 0) 250 { 251 ArchSpec::CPU cpu = thread.GetProcess().GetTarget().GetArchitecture().GetGenericCPUType(); 252 253 switch (exc_type) 254 { 255 case 1: // EXC_BAD_ACCESS 256 break; 257 258 case 2: // EXC_BAD_INSTRUCTION 259 switch (cpu) 260 { 261 case ArchSpec::eCPU_ppc: 262 case ArchSpec::eCPU_ppc64: 263 switch (exc_code) 264 { 265 case 1: // EXC_PPC_INVALID_SYSCALL 266 case 2: // EXC_PPC_UNIPL_INST 267 case 3: // EXC_PPC_PRIVINST 268 case 4: // EXC_PPC_PRIVREG 269 break; 270 case 5: // EXC_PPC_TRACE 271 return StopInfo::CreateStopReasonToTrace (thread); 272 case 6: // EXC_PPC_PERFMON 273 break; 274 } 275 break; 276 277 default: 278 break; 279 } 280 break; 281 282 case 3: // EXC_ARITHMETIC 283 case 4: // EXC_EMULATION 284 break; 285 286 case 5: // EXC_SOFTWARE 287 if (exc_code == 0x10003) // EXC_SOFT_SIGNAL 288 return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code); 289 break; 290 291 case 6: // EXC_BREAKPOINT 292 { 293 bool is_software_breakpoint = false; 294 switch (cpu) 295 { 296 case ArchSpec::eCPU_i386: 297 case ArchSpec::eCPU_x86_64: 298 if (exc_code == 1) // EXC_I386_SGL 299 { 300 return StopInfo::CreateStopReasonToTrace(thread); 301 } 302 else if (exc_code == 2) // EXC_I386_BPT 303 { 304 is_software_breakpoint = true; 305 } 306 break; 307 308 case ArchSpec::eCPU_ppc: 309 case ArchSpec::eCPU_ppc64: 310 is_software_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT 311 break; 312 313 case ArchSpec::eCPU_arm: 314 is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT 315 break; 316 317 default: 318 break; 319 } 320 321 if (is_software_breakpoint) 322 { 323 addr_t pc = thread.GetRegisterContext()->GetPC(); 324 lldb::BreakpointSiteSP bp_site_sp = thread.GetProcess().GetBreakpointSiteList().FindByAddress(pc); 325 if (bp_site_sp) 326 { 327 // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, 328 // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that 329 // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. 330 if (bp_site_sp->ValidForThisThread (&thread)) 331 return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID()); 332 else 333 return StopInfoSP(); 334 } 335 336 } 337 } 338 break; 339 340 case 7: // EXC_SYSCALL 341 case 8: // EXC_MACH_SYSCALL 342 case 9: // EXC_RPC_ALERT 343 case 10: // EXC_CRASH 344 break; 345 } 346 347 return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code)); 348 } 349 return StopInfoSP(); 350 } 351