darwin-fallback.c revision 169689
1290931Srodrigc/* Fallback frame-state unwinder for Darwin. 2290931Srodrigc Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3290931Srodrigc 4290931Srodrigc This file is part of GCC. 5290931Srodrigc 6290931Srodrigc GCC is free software; you can redistribute it and/or modify it 7290931Srodrigc under the terms of the GNU General Public License as published by 8290931Srodrigc the Free Software Foundation; either version 2, or (at your option) 9290931Srodrigc any later version. 10290931Srodrigc 11290931Srodrigc In addition to the permissions in the GNU General Public License, the 12290931Srodrigc Free Software Foundation gives you unlimited permission to link the 13290931Srodrigc compiled version of this file into combinations with other programs, 14290931Srodrigc and to distribute those combinations without any restriction coming 15290931Srodrigc from the use of this file. (The General Public License restrictions 16290931Srodrigc do apply in other respects; for example, they cover modification of 17290931Srodrigc the file, and distribution when not linked into a combined 18290931Srodrigc executable.) 19290931Srodrigc 20290931Srodrigc GCC is distributed in the hope that it will be useful, but WITHOUT 21290931Srodrigc ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 22290931Srodrigc or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 23290931Srodrigc License for more details. 24290931Srodrigc 25290931Srodrigc You should have received a copy of the GNU General Public License 26290931Srodrigc along with GCC; see the file COPYING. If not, write to the Free 27290931Srodrigc Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 28290931Srodrigc 02110-1301, USA. */ 29290931Srodrigc 30290931Srodrigc#include "tconfig.h" 31290931Srodrigc#include "tsystem.h" 32290931Srodrigc#include "coretypes.h" 33290931Srodrigc#include "tm.h" 34290931Srodrigc#include "dwarf2.h" 35290931Srodrigc#include "unwind.h" 36290931Srodrigc#include "unwind-dw2.h" 37290931Srodrigc#include <stdint.h> 38290931Srodrigc#include <stdbool.h> 39290931Srodrigc#include <sys/types.h> 40290931Srodrigc#include <signal.h> 41290931Srodrigc 42290931Srodrigctypedef unsigned long reg_unit; 43290931Srodrigc 44290931Srodrigc/* Place in GPRS the parameters to the first 'sc' instruction that would 45290931Srodrigc have been executed if we were returning from this CONTEXT, or 46290931Srodrigc return false if an unexpected instruction is encountered. */ 47290931Srodrigc 48290931Srodrigcstatic bool 49290931Srodrigcinterpret_libc (reg_unit gprs[32], struct _Unwind_Context *context) 50290931Srodrigc{ 51290931Srodrigc uint32_t *pc = (uint32_t *)_Unwind_GetIP (context); 52290931Srodrigc uint32_t cr; 53290931Srodrigc reg_unit lr = (reg_unit) pc; 54290931Srodrigc reg_unit ctr = 0; 55290931Srodrigc uint32_t *invalid_address = NULL; 56290931Srodrigc 57290931Srodrigc int i; 58290931Srodrigc 59290931Srodrigc for (i = 0; i < 13; i++) 60290931Srodrigc gprs[i] = 1; 61290931Srodrigc gprs[1] = _Unwind_GetCFA (context); 62290931Srodrigc for (; i < 32; i++) 63290931Srodrigc gprs[i] = _Unwind_GetGR (context, i); 64290931Srodrigc cr = _Unwind_GetGR (context, CR2_REGNO); 65290931Srodrigc 66290931Srodrigc /* For each supported Libc, we have to track the code flow 67290931Srodrigc all the way back into the kernel. 68290931Srodrigc 69290931Srodrigc This code is believed to support all released Libc/Libsystem builds since 70290931Srodrigc Jaguar 6C115, including all the security updates. To be precise, 71290931Srodrigc 72290931Srodrigc Libc Libsystem Build(s) 73290931Srodrigc 262~1 60~37 6C115 74290931Srodrigc 262~1 60.2~4 6D52 75290931Srodrigc 262~1 61~3 6F21-6F22 76290931Srodrigc 262~1 63~24 6G30-6G37 77290931Srodrigc 262~1 63~32 6I34-6I35 78290931Srodrigc 262~1 63~64 6L29-6L60 79290931Srodrigc 262.4.1~1 63~84 6L123-6R172 80290931Srodrigc 81290931Srodrigc 320~1 71~101 7B85-7D28 82290931Srodrigc 320~1 71~266 7F54-7F56 83290931Srodrigc 320~1 71~288 7F112 84290931Srodrigc 320~1 71~289 7F113 85290931Srodrigc 320.1.3~1 71.1.1~29 7H60-7H105 86290931Srodrigc 320.1.3~1 71.1.1~30 7H110-7H113 87290931Srodrigc 320.1.3~1 71.1.1~31 7H114 88290931Srodrigc 89290931Srodrigc That's a big table! It would be insane to try to keep track of 90290931Srodrigc every little detail, so we just read the code itself and do what 91290931Srodrigc it would do. 92290931Srodrigc */ 93290931Srodrigc 94290931Srodrigc for (;;) 95290931Srodrigc { 96290931Srodrigc uint32_t ins = *pc++; 97290931Srodrigc 98290931Srodrigc if ((ins & 0xFC000003) == 0x48000000) /* b instruction */ 99290931Srodrigc { 100290931Srodrigc pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4; 101290931Srodrigc continue; 102290931Srodrigc } 103290931Srodrigc if ((ins & 0xFC600000) == 0x2C000000) /* cmpwi */ 104290931Srodrigc { 105290931Srodrigc int32_t val1 = (int16_t) ins; 106290931Srodrigc int32_t val2 = gprs[ins >> 16 & 0x1F]; 107290931Srodrigc /* Only beq and bne instructions are supported, so we only 108290931Srodrigc need to set the EQ bit. */ 109290931Srodrigc uint32_t mask = 0xF << ((ins >> 21 & 0x1C) ^ 0x1C); 110290931Srodrigc if (val1 == val2) 111290931Srodrigc cr |= mask; 112290931Srodrigc else 113290931Srodrigc cr &= ~mask; 114290931Srodrigc continue; 115290931Srodrigc } 116290931Srodrigc if ((ins & 0xFEC38003) == 0x40820000) /* forwards beq/bne */ 117290931Srodrigc { 118290931Srodrigc if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1)) 119290931Srodrigc pc += (ins & 0x7FFC) / 4 - 1; 120290931Srodrigc continue; 121290931Srodrigc } 122290931Srodrigc if ((ins & 0xFC0007FF) == 0x7C000378) /* or, including mr */ 123290931Srodrigc { 124290931Srodrigc gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F] 125290931Srodrigc | gprs [ins >> 21 & 0x1F]); 126290931Srodrigc continue; 127290931Srodrigc } 128290931Srodrigc if (ins >> 26 == 0x0E) /* addi, including li */ 129290931Srodrigc { 130290931Srodrigc reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; 131290931Srodrigc gprs [ins >> 21 & 0x1F] = src + (int16_t) ins; 132290931Srodrigc continue; 133290931Srodrigc } 134290931Srodrigc if (ins >> 26 == 0x0F) /* addis, including lis */ 135290931Srodrigc { 136290931Srodrigc reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; 137290931Srodrigc gprs [ins >> 21 & 0x1F] = src + ((int16_t) ins << 16); 138290931Srodrigc continue; 139290931Srodrigc } 140290931Srodrigc if (ins >> 26 == 0x20) /* lwz */ 141290931Srodrigc { 142290931Srodrigc reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; 143290931Srodrigc uint32_t *p = (uint32_t *)(src + (int16_t) ins); 144290931Srodrigc if (p == invalid_address) 145290931Srodrigc return false; 146290931Srodrigc gprs [ins >> 21 & 0x1F] = *p; 147290931Srodrigc continue; 148290931Srodrigc } 149290931Srodrigc if (ins >> 26 == 0x21) /* lwzu */ 150290931Srodrigc { 151290931Srodrigc uint32_t *p = (uint32_t *)(gprs [ins >> 16 & 0x1F] += (int16_t) ins); 152290931Srodrigc if (p == invalid_address) 153290931Srodrigc return false; 154290931Srodrigc gprs [ins >> 21 & 0x1F] = *p; 155290931Srodrigc continue; 156290931Srodrigc } 157290931Srodrigc if (ins >> 26 == 0x24) /* stw */ 158290931Srodrigc /* What we hope this is doing is '--in_sigtramp'. We don't want 159290931Srodrigc to actually store to memory, so just make a note of the 160290931Srodrigc address and refuse to load from it. */ 161290931Srodrigc { 162290931Srodrigc reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; 163290931Srodrigc uint32_t *p = (uint32_t *)(src + (int16_t) ins); 164290931Srodrigc if (p == NULL || invalid_address != NULL) 165290931Srodrigc return false; 166290931Srodrigc invalid_address = p; 167290931Srodrigc continue; 168290931Srodrigc } 169290931Srodrigc if (ins >> 26 == 0x2E) /* lmw */ 170290931Srodrigc { 171290931Srodrigc reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F]; 172290931Srodrigc uint32_t *p = (uint32_t *)(src + (int16_t) ins); 173290931Srodrigc int i; 174290931Srodrigc 175290931Srodrigc for (i = (ins >> 21 & 0x1F); i < 32; i++) 176290931Srodrigc { 177290931Srodrigc if (p == invalid_address) 178290931Srodrigc return false; 179290931Srodrigc gprs[i] = *p++; 180290931Srodrigc } 181290931Srodrigc continue; 182290931Srodrigc } 183290931Srodrigc if ((ins & 0xFC1FFFFF) == 0x7c0803a6) /* mtlr */ 184290931Srodrigc { 185290931Srodrigc lr = gprs [ins >> 21 & 0x1F]; 186290931Srodrigc continue; 187290931Srodrigc } 188290931Srodrigc if ((ins & 0xFC1FFFFF) == 0x7c0802a6) /* mflr */ 189290931Srodrigc { 190290931Srodrigc gprs [ins >> 21 & 0x1F] = lr; 191290931Srodrigc continue; 192290931Srodrigc } 193290931Srodrigc if ((ins & 0xFC1FFFFF) == 0x7c0903a6) /* mtctr */ 194290931Srodrigc { 195290931Srodrigc ctr = gprs [ins >> 21 & 0x1F]; 196290931Srodrigc continue; 197290931Srodrigc } 198290931Srodrigc /* The PowerPC User's Manual says that bit 11 of the mtcrf 199290931Srodrigc instruction is reserved and should be set to zero, but it 200290931Srodrigc looks like the Darwin assembler doesn't do that... */ 201290931Srodrigc if ((ins & 0xFC000FFF) == 0x7c000120) /* mtcrf */ 202290931Srodrigc { 203290931Srodrigc int i; 204290931Srodrigc uint32_t mask = 0; 205290931Srodrigc for (i = 0; i < 8; i++) 206290931Srodrigc mask |= ((-(ins >> (12 + i) & 1)) & 0xF) << 4 * i; 207290931Srodrigc cr = (cr & ~mask) | (gprs [ins >> 21 & 0x1F] & mask); 208290931Srodrigc continue; 209290931Srodrigc } 210290931Srodrigc if (ins == 0x429f0005) /* bcl- 20,4*cr7+so,.+4, loads pc into LR */ 211290931Srodrigc { 212290931Srodrigc lr = (reg_unit) pc; 213290931Srodrigc continue; 214290931Srodrigc } 215290931Srodrigc if (ins == 0x4e800420) /* bctr */ 216290931Srodrigc { 217290931Srodrigc pc = (uint32_t *) ctr; 218290934Srodrigc continue; 219290931Srodrigc } 220290931Srodrigc if (ins == 0x44000002) /* sc */ 221290931Srodrigc return true; 222290931Srodrigc 223290931Srodrigc return false; 224290931Srodrigc } 225290931Srodrigc} 226290931Srodrigc 227290931Srodrigc/* We used to include <ucontext.h> and <mach/thread_status.h>, 228290931Srodrigc but they change so much between different Darwin system versions 229290931Srodrigc that it's much easier to just write the structures involved here 230290931Srodrigc directly. */ 231290931Srodrigc 232290931Srodrigc/* These defines are from the kernel's bsd/dev/ppc/unix_signal.c. */ 233290931Srodrigc#define UC_TRAD 1 234290931Srodrigc#define UC_TRAD_VEC 6 235290931Srodrigc#define UC_TRAD64 20 236290931Srodrigc#define UC_TRAD64_VEC 25 237290931Srodrigc#define UC_FLAVOR 30 238290931Srodrigc#define UC_FLAVOR_VEC 35 239290931Srodrigc#define UC_FLAVOR64 40 240290931Srodrigc#define UC_FLAVOR64_VEC 45 241290931Srodrigc#define UC_DUAL 50 242290931Srodrigc#define UC_DUAL_VEC 55 243290931Srodrigc 244290931Srodrigcstruct gcc_ucontext 245290931Srodrigc{ 246290931Srodrigc int onstack; 247290931Srodrigc sigset_t sigmask; 248290931Srodrigc void * stack_sp; 249290931Srodrigc size_t stack_sz; 250290931Srodrigc int stack_flags; 251290931Srodrigc struct gcc_ucontext *link; 252290931Srodrigc size_t mcsize; 253290931Srodrigc struct gcc_mcontext32 *mcontext; 254}; 255 256struct gcc_float_vector_state 257{ 258 double fpregs[32]; 259 uint32_t fpscr_pad; 260 uint32_t fpscr; 261 uint32_t save_vr[32][4]; 262 uint32_t save_vscr[4]; 263}; 264 265struct gcc_mcontext32 { 266 uint32_t dar; 267 uint32_t dsisr; 268 uint32_t exception; 269 uint32_t padding1[5]; 270 uint32_t srr0; 271 uint32_t srr1; 272 uint32_t gpr[32]; 273 uint32_t cr; 274 uint32_t xer; 275 uint32_t lr; 276 uint32_t ctr; 277 uint32_t mq; 278 uint32_t vrsave; 279 struct gcc_float_vector_state fvs; 280}; 281 282/* These are based on /usr/include/ppc/ucontext.h and 283 /usr/include/mach/ppc/thread_status.h, but rewritten to be more 284 convenient, to compile on Jaguar, and to work around Radar 3712064 285 on Panther, which is that the 'es' field of 'struct mcontext64' has 286 the wrong type (doh!). */ 287 288struct gcc_mcontext64 { 289 uint64_t dar; 290 uint32_t dsisr; 291 uint32_t exception; 292 uint32_t padding1[4]; 293 uint64_t srr0; 294 uint64_t srr1; 295 uint32_t gpr[32][2]; 296 uint32_t cr; 297 uint32_t xer[2]; /* These are arrays because the original structure has them misaligned. */ 298 uint32_t lr[2]; 299 uint32_t ctr[2]; 300 uint32_t vrsave; 301 struct gcc_float_vector_state fvs; 302}; 303 304#define UC_FLAVOR_SIZE \ 305 (sizeof (struct gcc_mcontext32) - 33*16) 306 307#define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32)) 308 309#define UC_FLAVOR64_SIZE \ 310 (sizeof (struct gcc_mcontext64) - 33*16) 311 312#define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64)) 313 314/* Given GPRS as input to a 'sc' instruction, and OLD_CFA, update FS 315 to represent the execution of a signal return; or, if not a signal 316 return, return false. */ 317 318static bool 319handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32], 320 _Unwind_Ptr old_cfa) 321{ 322 struct gcc_ucontext *uctx; 323 bool is_64, is_vector; 324 struct gcc_float_vector_state * float_vector_state; 325 _Unwind_Ptr new_cfa; 326 int i; 327 static _Unwind_Ptr return_addr; 328 329 /* Yay! We're in a Libc that we understand, and it's made a 330 system call. It'll be one of two kinds: either a Jaguar-style 331 SYS_sigreturn, or a Panther-style 'syscall' call with 184, which 332 is also SYS_sigreturn. */ 333 334 if (gprs[0] == 0x67 /* SYS_SIGRETURN */) 335 { 336 uctx = (struct gcc_ucontext *) gprs[3]; 337 is_vector = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE 338 || uctx->mcsize == UC_FLAVOR_VEC_SIZE); 339 is_64 = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE 340 || uctx->mcsize == UC_FLAVOR64_SIZE); 341 } 342 else if (gprs[0] == 0 && gprs[3] == 184) 343 { 344 int ctxstyle = gprs[5]; 345 uctx = (struct gcc_ucontext *) gprs[4]; 346 is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC 347 || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC); 348 is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC 349 || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64); 350 } 351 else 352 return false; 353 354#define set_offset(r, addr) \ 355 (fs->regs.reg[r].how = REG_SAVED_OFFSET, \ 356 fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa) 357 358 /* Restore even the registers that are not call-saved, since they 359 might be being used in the prologue to save other registers, 360 for instance GPR0 is sometimes used to save LR. */ 361 362 /* Handle the GPRs, and produce the information needed to do the rest. */ 363 if (is_64) 364 { 365 /* The context is 64-bit, but it doesn't carry any extra information 366 for us because only the low 32 bits of the registers are 367 call-saved. */ 368 struct gcc_mcontext64 *m64 = (struct gcc_mcontext64 *)uctx->mcontext; 369 int i; 370 371 float_vector_state = &m64->fvs; 372 373 new_cfa = m64->gpr[1][1]; 374 375 set_offset (CR2_REGNO, &m64->cr); 376 for (i = 0; i < 32; i++) 377 set_offset (i, m64->gpr[i] + 1); 378 set_offset (XER_REGNO, m64->xer + 1); 379 set_offset (LINK_REGISTER_REGNUM, m64->lr + 1); 380 set_offset (COUNT_REGISTER_REGNUM, m64->ctr + 1); 381 if (is_vector) 382 set_offset (VRSAVE_REGNO, &m64->vrsave); 383 384 /* Sometimes, srr0 points to the instruction that caused the exception, 385 and sometimes to the next instruction to be executed; we want 386 the latter. */ 387 if (m64->exception == 3 || m64->exception == 4 388 || m64->exception == 6 389 || (m64->exception == 7 && !(m64->srr1 & 0x10000))) 390 return_addr = m64->srr0 + 4; 391 else 392 return_addr = m64->srr0; 393 } 394 else 395 { 396 struct gcc_mcontext32 *m = uctx->mcontext; 397 int i; 398 399 float_vector_state = &m->fvs; 400 401 new_cfa = m->gpr[1]; 402 403 set_offset (CR2_REGNO, &m->cr); 404 for (i = 0; i < 32; i++) 405 set_offset (i, m->gpr + i); 406 set_offset (XER_REGNO, &m->xer); 407 set_offset (LINK_REGISTER_REGNUM, &m->lr); 408 set_offset (COUNT_REGISTER_REGNUM, &m->ctr); 409 410 if (is_vector) 411 set_offset (VRSAVE_REGNO, &m->vrsave); 412 413 /* Sometimes, srr0 points to the instruction that caused the exception, 414 and sometimes to the next instruction to be executed; we want 415 the latter. */ 416 if (m->exception == 3 || m->exception == 4 417 || m->exception == 6 418 || (m->exception == 7 && !(m->srr1 & 0x10000))) 419 return_addr = m->srr0 + 4; 420 else 421 return_addr = m->srr0; 422 } 423 424 fs->cfa_how = CFA_REG_OFFSET; 425 fs->cfa_reg = STACK_POINTER_REGNUM; 426 fs->cfa_offset = new_cfa - old_cfa;; 427 428 /* The choice of column for the return address is somewhat tricky. 429 Fortunately, the actual choice is private to this file, and 430 the space it's reserved from is the GCC register space, not the 431 DWARF2 numbering. So any free element of the right size is an OK 432 choice. Thus: */ 433 fs->retaddr_column = ARG_POINTER_REGNUM; 434 /* FIXME: this should really be done using a DWARF2 location expression, 435 not using a static variable. In fact, this entire file should 436 be implemented in DWARF2 expressions. */ 437 set_offset (ARG_POINTER_REGNUM, &return_addr); 438 439 for (i = 0; i < 32; i++) 440 set_offset (32 + i, float_vector_state->fpregs + i); 441 set_offset (SPEFSCR_REGNO, &float_vector_state->fpscr); 442 443 if (is_vector) 444 { 445 for (i = 0; i < 32; i++) 446 set_offset (FIRST_ALTIVEC_REGNO + i, float_vector_state->save_vr + i); 447 set_offset (VSCR_REGNO, float_vector_state->save_vscr); 448 } 449 450 return true; 451} 452 453/* This is also prototyped in rs6000/darwin.h, inside the 454 MD_FALLBACK_FRAME_STATE_FOR macro. */ 455extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context *context, 456 _Unwind_FrameState *fs); 457 458/* Implement the MD_FALLBACK_FRAME_STATE_FOR macro, 459 returning true iff the frame was a sigreturn() frame that we 460 can understand. */ 461 462bool 463_Unwind_fallback_frame_state_for (struct _Unwind_Context *context, 464 _Unwind_FrameState *fs) 465{ 466 reg_unit gprs[32]; 467 468 if (!interpret_libc (gprs, context)) 469 return false; 470 return handle_syscall (fs, gprs, _Unwind_GetCFA (context)); 471} 472