00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "tconfig.h"
00031 #include "tsystem.h"
00032 #include "coretypes.h"
00033 #include "tm.h"
00034 #include "dwarf2.h"
00035 #include "unwind.h"
00036 #include "unwind-dw2.h"
00037 #include <stdint.h>
00038 #include <stdbool.h>
00039 #include <signal.h>
00040 #include <ucontext.h>
00041 #include <mach/thread_status.h>
00042
00043 typedef unsigned long reg_unit;
00044
00045
00046
00047
00048
00049 static bool
00050 interpret_libc (reg_unit gprs[32], struct _Unwind_Context *context)
00051 {
00052 uint32_t *pc = (uint32_t *)_Unwind_GetIP (context);
00053 uint32_t cr;
00054 reg_unit lr = (reg_unit) pc;
00055 reg_unit ctr = 0;
00056 uint32_t *invalid_address = NULL;
00057
00058 int i;
00059
00060 for (i = 0; i < 13; i++)
00061 gprs[i] = 1;
00062 gprs[1] = _Unwind_GetCFA (context);
00063 for (; i < 32; i++)
00064 gprs[i] = _Unwind_GetGR (context, i);
00065 cr = _Unwind_GetGR (context, CR2_REGNO);
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 for (;;)
00096 {
00097 uint32_t ins = *pc++;
00098
00099 if ((ins & 0xFC000003) == 0x48000000)
00100 {
00101 pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4;
00102 continue;
00103 }
00104 if ((ins & 0xFC600000) == 0x2C000000)
00105 {
00106 int32_t val1 = (int16_t) ins;
00107 int32_t val2 = gprs[ins >> 16 & 0x1F];
00108
00109
00110 uint32_t mask = 0xF << ((ins >> 21 & 0x1C) ^ 0x1C);
00111 if (val1 == val2)
00112 cr |= mask;
00113 else
00114 cr &= ~mask;
00115 continue;
00116 }
00117 if ((ins & 0xFEC38003) == 0x40820000)
00118 {
00119 if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1))
00120 pc += (ins & 0x7FFC) / 4 - 1;
00121 continue;
00122 }
00123 if ((ins & 0xFC0007FF) == 0x7C000378)
00124 {
00125 gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F]
00126 | gprs [ins >> 21 & 0x1F]);
00127 continue;
00128 }
00129 if (ins >> 26 == 0x0E)
00130 {
00131 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
00132 gprs [ins >> 21 & 0x1F] = src + (int16_t) ins;
00133 continue;
00134 }
00135 if (ins >> 26 == 0x0F)
00136 {
00137 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
00138 gprs [ins >> 21 & 0x1F] = src + ((int16_t) ins << 16);
00139 continue;
00140 }
00141 if (ins >> 26 == 0x20)
00142 {
00143 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
00144 uint32_t *p = (uint32_t *)(src + (int16_t) ins);
00145 if (p == invalid_address)
00146 return false;
00147 gprs [ins >> 21 & 0x1F] = *p;
00148 continue;
00149 }
00150 if (ins >> 26 == 0x21)
00151 {
00152 uint32_t *p = (uint32_t *)(gprs [ins >> 16 & 0x1F] += (int16_t) ins);
00153 if (p == invalid_address)
00154 return false;
00155 gprs [ins >> 21 & 0x1F] = *p;
00156 continue;
00157 }
00158 if (ins >> 26 == 0x24)
00159
00160
00161
00162 {
00163 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
00164 uint32_t *p = (uint32_t *)(src + (int16_t) ins);
00165 if (p == NULL || invalid_address != NULL)
00166 return false;
00167 invalid_address = p;
00168 continue;
00169 }
00170 if (ins >> 26 == 0x2E)
00171 {
00172 reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
00173 uint32_t *p = (uint32_t *)(src + (int16_t) ins);
00174 int i;
00175
00176 for (i = (ins >> 21 & 0x1F); i < 32; i++)
00177 {
00178 if (p == invalid_address)
00179 return false;
00180 gprs[i] = *p++;
00181 }
00182 continue;
00183 }
00184 if ((ins & 0xFC1FFFFF) == 0x7c0803a6)
00185 {
00186 lr = gprs [ins >> 21 & 0x1F];
00187 continue;
00188 }
00189 if ((ins & 0xFC1FFFFF) == 0x7c0802a6)
00190 {
00191 gprs [ins >> 21 & 0x1F] = lr;
00192 continue;
00193 }
00194 if ((ins & 0xFC1FFFFF) == 0x7c0903a6)
00195 {
00196 ctr = gprs [ins >> 21 & 0x1F];
00197 continue;
00198 }
00199
00200
00201
00202 if ((ins & 0xFC000FFF) == 0x7c000120)
00203 {
00204 int i;
00205 uint32_t mask = 0;
00206 for (i = 0; i < 8; i++)
00207 mask |= ((-(ins >> (12 + i) & 1)) & 0xF) << 4 * i;
00208 cr = (cr & ~mask) | (gprs [ins >> 21 & 0x1F] & mask);
00209 continue;
00210 }
00211 if (ins == 0x429f0005)
00212 {
00213 lr = (reg_unit) pc;
00214 continue;
00215 }
00216 if (ins == 0x4e800420)
00217 {
00218 pc = (uint32_t *) ctr;
00219 continue;
00220 }
00221 if (ins == 0x44000002)
00222 return true;
00223
00224 return false;
00225 }
00226 }
00227
00228
00229 #define UC_TRAD 1
00230 #define UC_TRAD_VEC 6
00231 #define UC_TRAD64 20
00232 #define UC_TRAD64_VEC 25
00233 #define UC_FLAVOR 30
00234 #define UC_FLAVOR_VEC 35
00235 #define UC_FLAVOR64 40
00236 #define UC_FLAVOR64_VEC 45
00237 #define UC_DUAL 50
00238 #define UC_DUAL_VEC 55
00239
00240
00241
00242
00243
00244
00245
00246 struct gcc_mcontext64 {
00247 uint64_t dar;
00248 uint32_t dsisr;
00249 uint32_t exception;
00250 uint32_t padding1[4];
00251 uint64_t srr0;
00252 uint64_t srr1;
00253 uint32_t gpr[32][2];
00254 uint32_t cr;
00255 uint32_t xer[2];
00256 uint32_t lr[2];
00257 uint32_t ctr[2];
00258 uint32_t vrsave;
00259 ppc_float_state_t fs;
00260 ppc_vector_state_t vs;
00261 };
00262
00263 #define UC_FLAVOR_SIZE \
00264 (sizeof (struct mcontext) - sizeof (ppc_vector_state_t))
00265
00266 #define UC_FLAVOR_VEC_SIZE (sizeof (struct mcontext))
00267
00268 #define UC_FLAVOR64_SIZE \
00269 (sizeof (struct gcc_mcontext64) - sizeof (ppc_vector_state_t))
00270
00271 #define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64))
00272
00273
00274
00275
00276
00277 static bool
00278 handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32],
00279 _Unwind_Ptr old_cfa)
00280 {
00281 ucontext_t *uctx;
00282 bool is_64, is_vector;
00283 ppc_float_state_t *float_state;
00284 ppc_vector_state_t *vector_state;
00285 _Unwind_Ptr new_cfa;
00286 int i;
00287 static _Unwind_Ptr return_addr;
00288
00289
00290
00291
00292
00293
00294 if (gprs[0] == 0x67 )
00295 {
00296 uctx = (ucontext_t *) gprs[3];
00297 is_vector = (uctx->uc_mcsize == UC_FLAVOR64_VEC_SIZE
00298 || uctx->uc_mcsize == UC_FLAVOR_VEC_SIZE);
00299 is_64 = (uctx->uc_mcsize == UC_FLAVOR64_VEC_SIZE
00300 || uctx->uc_mcsize == UC_FLAVOR64_SIZE);
00301 }
00302 else if (gprs[0] == 0 && gprs[3] == 184)
00303 {
00304 int ctxstyle = gprs[5];
00305 uctx = (ucontext_t *) gprs[4];
00306 is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
00307 || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
00308 is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
00309 || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
00310 }
00311 else
00312 return false;
00313
00314 #define set_offset(r, addr) \
00315 (fs->regs.reg[r].how = REG_SAVED_OFFSET, \
00316 fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa)
00317
00318
00319
00320
00321
00322
00323 if (is_64)
00324 {
00325
00326
00327
00328 struct gcc_mcontext64 *m64 = (struct gcc_mcontext64 *)uctx->uc_mcontext;
00329 int i;
00330
00331 float_state = &m64->fs;
00332 vector_state = &m64->vs;
00333
00334 new_cfa = m64->gpr[1][1];
00335
00336 set_offset (CR2_REGNO, &m64->cr);
00337 for (i = 0; i < 32; i++)
00338 set_offset (i, m64->gpr[i] + 1);
00339 set_offset (XER_REGNO, m64->xer + 1);
00340 set_offset (LINK_REGISTER_REGNUM, m64->lr + 1);
00341 set_offset (COUNT_REGISTER_REGNUM, m64->ctr + 1);
00342 if (is_vector)
00343 set_offset (VRSAVE_REGNO, &m64->vrsave);
00344
00345
00346
00347
00348 if (m64->exception == 3 || m64->exception == 4
00349 || m64->exception == 6
00350 || (m64->exception == 7 && !(m64->srr1 & 0x10000)))
00351 return_addr = m64->srr0 + 4;
00352 else
00353 return_addr = m64->srr0;
00354 }
00355 else
00356 {
00357 struct mcontext *m = uctx->uc_mcontext;
00358 int i;
00359
00360 float_state = &m->fs;
00361 vector_state = &m->vs;
00362
00363 new_cfa = m->ss.r1;
00364
00365 set_offset (CR2_REGNO, &m->ss.cr);
00366 for (i = 0; i < 32; i++)
00367 set_offset (i, &m->ss.r0 + i);
00368 set_offset (XER_REGNO, &m->ss.xer);
00369 set_offset (LINK_REGISTER_REGNUM, &m->ss.lr);
00370 set_offset (COUNT_REGISTER_REGNUM, &m->ss.ctr);
00371
00372 if (is_vector)
00373 set_offset (VRSAVE_REGNO, &m->ss.vrsave);
00374
00375
00376
00377
00378 if (m->es.exception == 3 || m->es.exception == 4
00379 || m->es.exception == 6
00380 || (m->es.exception == 7 && !(m->ss.srr1 & 0x10000)))
00381 return_addr = m->ss.srr0 + 4;
00382 else
00383 return_addr = m->ss.srr0;
00384 }
00385
00386 fs->cfa_how = CFA_REG_OFFSET;
00387 fs->cfa_reg = STACK_POINTER_REGNUM;
00388 fs->cfa_offset = new_cfa - old_cfa;;
00389
00390
00391
00392
00393
00394
00395 fs->retaddr_column = ARG_POINTER_REGNUM;
00396
00397
00398
00399 set_offset (ARG_POINTER_REGNUM, &return_addr);
00400
00401 for (i = 0; i < 32; i++)
00402 set_offset (32 + i, float_state->fpregs + i);
00403 set_offset (SPEFSCR_REGNO, &float_state->fpscr);
00404
00405 if (is_vector)
00406 {
00407 for (i = 0; i < 32; i++)
00408 set_offset (FIRST_ALTIVEC_REGNO + i, vector_state->save_vr + i);
00409 set_offset (VSCR_REGNO, vector_state->save_vscr);
00410 }
00411
00412 return true;
00413 }
00414
00415
00416
00417 extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
00418 _Unwind_FrameState *fs);
00419
00420
00421
00422
00423
00424 bool
00425 _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
00426 _Unwind_FrameState *fs)
00427 {
00428 reg_unit gprs[32];
00429
00430 if (!interpret_libc (gprs, context))
00431 return false;
00432 return handle_syscall (fs, gprs, _Unwind_GetCFA (context));
00433 }