163d1a8abSmrg /* DWARF2 EH unwinding support for AIX.
2*ec02198aSmrg Copyright (C) 2011-2020 Free Software Foundation, Inc.
363d1a8abSmrg
463d1a8abSmrg This file is part of GCC.
563d1a8abSmrg
663d1a8abSmrg GCC is free software; you can redistribute it and/or modify it
763d1a8abSmrg under the terms of the GNU General Public License as published by
863d1a8abSmrg the Free Software Foundation; either version 3, or (at your option)
963d1a8abSmrg any later version.
1063d1a8abSmrg
1163d1a8abSmrg GCC is distributed in the hope that it will be useful, but WITHOUT
1263d1a8abSmrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1363d1a8abSmrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1463d1a8abSmrg License for more details.
1563d1a8abSmrg
1663d1a8abSmrg Under Section 7 of GPL version 3, you are granted additional
1763d1a8abSmrg permissions described in the GCC Runtime Library Exception, version
1863d1a8abSmrg 3.1, as published by the Free Software Foundation.
1963d1a8abSmrg
2063d1a8abSmrg You should have received a copy of the GNU General Public License and
2163d1a8abSmrg a copy of the GCC Runtime Library Exception along with this program;
2263d1a8abSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2363d1a8abSmrg <http://www.gnu.org/licenses/>. */
2463d1a8abSmrg
2563d1a8abSmrg /* Useful register numbers. */
2663d1a8abSmrg
27*ec02198aSmrg #define R_LR 65
28*ec02198aSmrg #define R_CR2 70
29*ec02198aSmrg #define R_XER 76
30*ec02198aSmrg #define R_FIRST_ALTIVEC 77
31*ec02198aSmrg #define R_VRSAVE 109
32*ec02198aSmrg #define R_VSCR 110
3363d1a8abSmrg
3463d1a8abSmrg /* If the current unwind info (FS) does not contain explicit info
3563d1a8abSmrg saving R2, then we have to do a minor amount of code reading to
3663d1a8abSmrg figure out if it was saved. The big problem here is that the
3763d1a8abSmrg code that does the save/restore is generated by the linker, so
3863d1a8abSmrg we have no good way to determine at compile time what to do. */
3963d1a8abSmrg
4063d1a8abSmrg #ifdef __64BIT__
4163d1a8abSmrg #define MD_FROB_UPDATE_CONTEXT(CTX, FS) \
4263d1a8abSmrg do { \
4363d1a8abSmrg if ((FS)->regs.reg[2].how == REG_UNSAVED) \
4463d1a8abSmrg { \
4563d1a8abSmrg unsigned int *insn \
4663d1a8abSmrg = (unsigned int *) \
47*ec02198aSmrg _Unwind_GetGR ((CTX), R_LR); \
4863d1a8abSmrg if (*insn == 0xE8410028) \
4963d1a8abSmrg _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 40); \
5063d1a8abSmrg } \
5163d1a8abSmrg } while (0)
5263d1a8abSmrg #else
5363d1a8abSmrg #define MD_FROB_UPDATE_CONTEXT(CTX, FS) \
5463d1a8abSmrg do { \
5563d1a8abSmrg if ((FS)->regs.reg[2].how == REG_UNSAVED) \
5663d1a8abSmrg { \
5763d1a8abSmrg unsigned int *insn \
5863d1a8abSmrg = (unsigned int *) \
59*ec02198aSmrg _Unwind_GetGR ((CTX), R_LR); \
6063d1a8abSmrg if (*insn == 0x80410014) \
6163d1a8abSmrg _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 20); \
6263d1a8abSmrg } \
6363d1a8abSmrg } while (0)
6463d1a8abSmrg #endif
6563d1a8abSmrg
6663d1a8abSmrg /* Now on to MD_FALLBACK_FRAME_STATE_FOR.
67c7a68eb7Smrg 32bit AIX 5.2, 5.3, 6.1, 7.X and
68c7a68eb7Smrg 64bit AIX 6.1, 7.X only at this stage. */
6963d1a8abSmrg
7063d1a8abSmrg #include <stdlib.h>
7163d1a8abSmrg #include <stddef.h>
7263d1a8abSmrg #include <signal.h>
7363d1a8abSmrg #include <sys/machine.h>
7463d1a8abSmrg
7563d1a8abSmrg #ifdef __64BIT__
7663d1a8abSmrg
7763d1a8abSmrg typedef struct __context64 mstate_t;
7863d1a8abSmrg
7963d1a8abSmrg #else
8063d1a8abSmrg
8163d1a8abSmrg typedef struct mstsave mstate_t;
8263d1a8abSmrg
8363d1a8abSmrg #endif
8463d1a8abSmrg
85c7a68eb7Smrg #define MD_FALLBACK_FRAME_STATE_FOR ppc_aix_fallback_frame_state
86c7a68eb7Smrg
8763d1a8abSmrg /* If we are compiling on AIX < 5.3, the VMX related datastructs are not
8863d1a8abSmrg defined and we take measures to obtain proper runtime behavior if the
8963d1a8abSmrg compiled code happens to run on a later version with VMX enabled. */
9063d1a8abSmrg
9163d1a8abSmrg #ifndef MSR_VMX
9263d1a8abSmrg #define MSR_VMX 0x2000000
9363d1a8abSmrg #endif
9463d1a8abSmrg
9563d1a8abSmrg typedef unsigned int uint;
9663d1a8abSmrg typedef struct { uint v[4]; } vreg_t;
9763d1a8abSmrg typedef struct {
9863d1a8abSmrg vreg_t regs[32];
9963d1a8abSmrg uint pad1 [3];
10063d1a8abSmrg uint vscr;
10163d1a8abSmrg uint vrsave;
10263d1a8abSmrg uint pad2 [3];
10363d1a8abSmrg } vstate_t;
10463d1a8abSmrg
10563d1a8abSmrg #define EXT_CONTEXT_MARK 0x45435458
10663d1a8abSmrg #define EXT_CONTEXT_SIZE 4096
10763d1a8abSmrg #define BUMPER_SIZE (EXT_CONTEXT_SIZE - sizeof(vstate_t) - (5 * sizeof(int)))
10863d1a8abSmrg
10963d1a8abSmrg typedef struct {
11063d1a8abSmrg uint pad1 [4];
11163d1a8abSmrg vstate_t vstate;
11263d1a8abSmrg char bumper [BUMPER_SIZE];
11363d1a8abSmrg int mark;
11463d1a8abSmrg } extended_context_t;
11563d1a8abSmrg
11663d1a8abSmrg typedef struct {
11763d1a8abSmrg char bumper [offsetof (ucontext_t, uc_stack) + sizeof (stack_t)];
11863d1a8abSmrg extended_context_t * ectx;
11963d1a8abSmrg int mark;
12063d1a8abSmrg } vmx_ucontext_t;
12163d1a8abSmrg
12263d1a8abSmrg /* Determine whether CONTEXT designates a signal handler, and return the
12363d1a8abSmrg associated ucontext_t address if so. Return NULL otherwise. */
12463d1a8abSmrg
12563d1a8abSmrg static ucontext_t *
ucontext_for(struct _Unwind_Context * context)12663d1a8abSmrg ucontext_for (struct _Unwind_Context *context)
12763d1a8abSmrg {
12863d1a8abSmrg const unsigned int * ra = context->ra;
12963d1a8abSmrg
130c7a68eb7Smrg /* AIX 5.2, 5.3, 6.1 and 7.X, threaded or not, share common patterns
13163d1a8abSmrg and feature variants depending on the configured kernel (unix_mp
13263d1a8abSmrg or unix_64). */
13363d1a8abSmrg
134c7a68eb7Smrg #ifdef __64BIT__
135c7a68eb7Smrg if (*(ra - 5) == 0x4c00012c /* isync */
136c7a68eb7Smrg && *(ra - 4) == 0xe8ec0000 /* ld r7,0(r12) */
137c7a68eb7Smrg && *(ra - 3) == 0xe84c0008 /* ld r2,8(r12) */
138c7a68eb7Smrg && *(ra - 2) == 0x7ce903a6 /* mtctr r7 */
139c7a68eb7Smrg && *(ra - 1) == 0x4e800421 /* bctrl */
140c7a68eb7Smrg && *(ra - 0) == 0x7de27b78) /* mr r2,r15 <-- context->ra */
141c7a68eb7Smrg {
142c7a68eb7Smrg /* unix_64 */
143c7a68eb7Smrg if (*(ra - 6) == 0x7d000164) /* mtmsrd r8 */
144c7a68eb7Smrg {
145c7a68eb7Smrg /* AIX 6.1, 7.1 and 7.2 */
146c7a68eb7Smrg return (ucontext_t *)(context->cfa + 0x70);
147c7a68eb7Smrg }
148c7a68eb7Smrg }
149c7a68eb7Smrg #else
15063d1a8abSmrg if (*(ra - 5) == 0x4c00012c /* isync */
15163d1a8abSmrg && *(ra - 4) == 0x80ec0000 /* lwz r7,0(r12) */
15263d1a8abSmrg && *(ra - 3) == 0x804c0004 /* lwz r2,4(r12) */
15363d1a8abSmrg && *(ra - 2) == 0x7ce903a6 /* mtctr r7 */
15463d1a8abSmrg && *(ra - 1) == 0x4e800421 /* bctrl */
15563d1a8abSmrg && *(ra - 0) == 0x7dc37378) /* mr r3,r14 <-- context->ra */
15663d1a8abSmrg {
15763d1a8abSmrg /* unix_64 */
15863d1a8abSmrg if (*(ra - 6) == 0x7d000164) /* mtmsrd r8 */
15963d1a8abSmrg {
16063d1a8abSmrg switch (*(ra + 18))
16163d1a8abSmrg {
16263d1a8abSmrg /* AIX 5.2 */
16363d1a8abSmrg case 0x835a0520: /* lwz r26,1312(r26) */
16463d1a8abSmrg return (ucontext_t *)(context->cfa + 0x70);
16563d1a8abSmrg
16663d1a8abSmrg /* AIX 5.3 */
16763d1a8abSmrg case 0x835a0570: /* lwz r26,1392(r26) */
16863d1a8abSmrg return (ucontext_t *)(context->cfa + 0x40);
16963d1a8abSmrg
170c7a68eb7Smrg /* AIX 6.1 and 7.1 */
17163d1a8abSmrg case 0x2c1a0000: /* cmpwi r26,0 */
17263d1a8abSmrg return (ucontext_t *)(context->cfa + 0x40);
17363d1a8abSmrg
174c7a68eb7Smrg /* AIX 7.2 */
175c7a68eb7Smrg case 0x3800000a: /* li r0,A */
176c7a68eb7Smrg return (ucontext_t *)(context->cfa + 0x40);
177c7a68eb7Smrg
17863d1a8abSmrg default:
17963d1a8abSmrg return 0;
18063d1a8abSmrg }
18163d1a8abSmrg }
18263d1a8abSmrg
18363d1a8abSmrg /* unix_mp */
18463d1a8abSmrg if (*(ra - 6) == 0x7d000124) /* mtmsr r8 */
18563d1a8abSmrg {
18663d1a8abSmrg typedef struct {
18763d1a8abSmrg char pad[56];
18863d1a8abSmrg ucontext_t ucontext;
18963d1a8abSmrg siginfo_t siginfo;
19063d1a8abSmrg } aix52_stack_t;
19163d1a8abSmrg
19263d1a8abSmrg aix52_stack_t * frame = (aix52_stack_t *) context->cfa;
19363d1a8abSmrg return &frame->ucontext;
19463d1a8abSmrg }
19563d1a8abSmrg }
196c7a68eb7Smrg #endif
19763d1a8abSmrg return 0;
19863d1a8abSmrg }
19963d1a8abSmrg
20063d1a8abSmrg /* The fallback proper. */
20163d1a8abSmrg
20263d1a8abSmrg #ifdef __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__
20363d1a8abSmrg #define RETURN_COLUMN __LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__
20463d1a8abSmrg #else
20563d1a8abSmrg #define RETURN_COLUMN ARG_POINTER_REGNUM
20663d1a8abSmrg #endif
20763d1a8abSmrg
20863d1a8abSmrg #define REGISTER_CFA_OFFSET_FOR(FS,REGNO,ADDR,CFA)\
20963d1a8abSmrg do { \
21063d1a8abSmrg (FS)->regs.reg[REGNO].how = REG_SAVED_OFFSET; \
21163d1a8abSmrg (FS)->regs.reg[REGNO].loc.offset = (long) (ADDR) - (CFA); \
212c7a68eb7Smrg } while (0)
21363d1a8abSmrg
21463d1a8abSmrg static _Unwind_Reason_Code
ppc_aix_fallback_frame_state(struct _Unwind_Context * context,_Unwind_FrameState * fs)21563d1a8abSmrg ppc_aix_fallback_frame_state (struct _Unwind_Context *context,
21663d1a8abSmrg _Unwind_FrameState *fs)
21763d1a8abSmrg {
21863d1a8abSmrg ucontext_t * uctx = ucontext_for (context);
21963d1a8abSmrg mstate_t * mctx;
22063d1a8abSmrg
22163d1a8abSmrg long new_cfa;
22263d1a8abSmrg int i;
22363d1a8abSmrg
22463d1a8abSmrg if (uctx == NULL)
22563d1a8abSmrg return _URC_END_OF_STACK;
22663d1a8abSmrg
22763d1a8abSmrg mctx = &uctx->uc_mcontext.jmp_context;
22863d1a8abSmrg
22963d1a8abSmrg /* The "kernel" frame cfa is the stack pointer at the signal occurrence
23063d1a8abSmrg point. */
23163d1a8abSmrg new_cfa = mctx->gpr[__LIBGCC_STACK_POINTER_REGNUM__];
23263d1a8abSmrg
23363d1a8abSmrg fs->regs.cfa_how = CFA_REG_OFFSET;
23463d1a8abSmrg fs->regs.cfa_reg = __LIBGCC_STACK_POINTER_REGNUM__;
23563d1a8abSmrg fs->regs.cfa_offset = new_cfa - (long) context->cfa;
23663d1a8abSmrg
23763d1a8abSmrg /* And we state how to find the various registers it has saved with
23863d1a8abSmrg relative offset rules from there. */
23963d1a8abSmrg
24063d1a8abSmrg for (i = 0; i < 32; i++)
24163d1a8abSmrg if (i != __LIBGCC_STACK_POINTER_REGNUM__)
24263d1a8abSmrg REGISTER_CFA_OFFSET_FOR (fs, i, &mctx->gpr[i], new_cfa);
24363d1a8abSmrg
244*ec02198aSmrg REGISTER_CFA_OFFSET_FOR (fs, R_CR2, &mctx->cr, new_cfa);
245*ec02198aSmrg REGISTER_CFA_OFFSET_FOR (fs, R_XER, &mctx->xer, new_cfa);
246*ec02198aSmrg REGISTER_CFA_OFFSET_FOR (fs, R_LR, &mctx->lr, new_cfa);
24763d1a8abSmrg
24863d1a8abSmrg fs->retaddr_column = RETURN_COLUMN;
24963d1a8abSmrg REGISTER_CFA_OFFSET_FOR (fs, RETURN_COLUMN, &mctx->iar, new_cfa);
25063d1a8abSmrg fs->signal_frame = 1;
25163d1a8abSmrg
25263d1a8abSmrg /* Honor FP Ever Used ... */
25363d1a8abSmrg if (mctx->fpeu)
25463d1a8abSmrg {
25563d1a8abSmrg for (i = 0; i < 32; i++)
25663d1a8abSmrg REGISTER_CFA_OFFSET_FOR (fs, i+32, &mctx->fpr[i], new_cfa);
25763d1a8abSmrg }
25863d1a8abSmrg
25963d1a8abSmrg /* Honor VMX context, if any. We expect the msr bit never to be set in
26063d1a8abSmrg environments where there is no VMX support, e.g. on AIX < 5.3. */
26163d1a8abSmrg if (mctx->msr & MSR_VMX)
26263d1a8abSmrg {
26363d1a8abSmrg vmx_ucontext_t * uc = (vmx_ucontext_t *) uctx;
26463d1a8abSmrg
26563d1a8abSmrg if (uc->mark == EXT_CONTEXT_MARK && uc->ectx->mark == EXT_CONTEXT_MARK)
26663d1a8abSmrg {
26763d1a8abSmrg vstate_t * vstate = &uc->ectx->vstate;
26863d1a8abSmrg
26963d1a8abSmrg for (i = 0; i < 32; i++)
27063d1a8abSmrg REGISTER_CFA_OFFSET_FOR
271*ec02198aSmrg (fs, i+R_FIRST_ALTIVEC, &vstate->regs[i], new_cfa);
27263d1a8abSmrg
273*ec02198aSmrg REGISTER_CFA_OFFSET_FOR (fs, R_VSCR, &vstate->vscr, new_cfa);
274*ec02198aSmrg REGISTER_CFA_OFFSET_FOR (fs, R_VRSAVE, &vstate->vrsave, new_cfa);
27563d1a8abSmrg }
27663d1a8abSmrg }
27763d1a8abSmrg
27863d1a8abSmrg return _URC_NO_REASON;
27963d1a8abSmrg }
280