Lines 78-154
Link Here
|
78 |
state data appropriately. See unwind-dw2.c for the structs. */ |
78 |
state data appropriately. See unwind-dw2.c for the structs. */ |
79 |
|
79 |
|
80 |
#ifdef IN_LIBGCC2 |
80 |
#ifdef IN_LIBGCC2 |
81 |
#include <signal.h> |
|
|
82 |
#include <sys/ucontext.h> |
83 |
|
81 |
|
84 |
enum { SIGNAL_FRAMESIZE = 64 }; |
82 |
enum { SIGNAL_FRAMESIZE = 64 }; |
85 |
#endif |
83 |
#endif |
86 |
|
84 |
|
87 |
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \ |
|
|
88 |
do { \ |
89 |
unsigned char *pc_ = (CONTEXT)->ra; \ |
90 |
struct sigcontext *sc_; \ |
91 |
long new_cfa_; \ |
92 |
int i_; \ |
93 |
\ |
94 |
/* li r0, 0x7777; sc (sigreturn old) */ \ |
95 |
/* li r0, 0x0077; sc (sigreturn new) */ \ |
96 |
/* li r0, 0x6666; sc (rt_sigreturn old) */ \ |
97 |
/* li r0, 0x00AC; sc (rt_sigreturn new) */ \ |
98 |
if (*(unsigned int *) (pc_+4) != 0x44000002) \ |
99 |
break; \ |
100 |
if (*(unsigned int *) (pc_+0) == 0x38007777 \ |
101 |
|| *(unsigned int *) (pc_+0) == 0x38000077) \ |
102 |
{ \ |
103 |
struct sigframe { \ |
104 |
char gap[SIGNAL_FRAMESIZE]; \ |
105 |
struct sigcontext sigctx; \ |
106 |
} *rt_ = (CONTEXT)->cfa; \ |
107 |
sc_ = &rt_->sigctx; \ |
108 |
} \ |
109 |
else if (*(unsigned int *) (pc_+0) == 0x38006666 \ |
110 |
|| *(unsigned int *) (pc_+0) == 0x380000AC) \ |
111 |
{ \ |
112 |
struct rt_sigframe { \ |
113 |
char gap[SIGNAL_FRAMESIZE]; \ |
114 |
unsigned long _unused[2]; \ |
115 |
struct siginfo *pinfo; \ |
116 |
void *puc; \ |
117 |
struct siginfo info; \ |
118 |
struct ucontext uc; \ |
119 |
} *rt_ = (CONTEXT)->cfa; \ |
120 |
sc_ = &rt_->uc.uc_mcontext; \ |
121 |
} \ |
122 |
else \ |
123 |
break; \ |
124 |
\ |
125 |
new_cfa_ = sc_->regs->gpr[STACK_POINTER_REGNUM]; \ |
126 |
(FS)->cfa_how = CFA_REG_OFFSET; \ |
127 |
(FS)->cfa_reg = STACK_POINTER_REGNUM; \ |
128 |
(FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \ |
129 |
\ |
130 |
for (i_ = 0; i_ < 32; i_++) \ |
131 |
if (i_ != STACK_POINTER_REGNUM) \ |
132 |
{ \ |
133 |
(FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \ |
134 |
(FS)->regs.reg[i_].loc.offset \ |
135 |
= (long)&(sc_->regs->gpr[i_]) - new_cfa_; \ |
136 |
} \ |
137 |
\ |
138 |
(FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \ |
139 |
(FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \ |
140 |
= (long)&(sc_->regs->link) - new_cfa_; \ |
141 |
\ |
142 |
/* The unwinder expects the IP to point to the following insn, \ |
143 |
whereas the kernel returns the address of the actual \ |
144 |
faulting insn. We store NIP+4 in an unused register slot to \ |
145 |
get the same result for multiple evaluation of the same signal \ |
146 |
frame. */ \ |
147 |
sc_->regs->gpr[47] = sc_->regs->nip + 4; \ |
148 |
(FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET; \ |
149 |
(FS)->regs.reg[CR0_REGNO].loc.offset \ |
150 |
= (long)&(sc_->regs->gpr[47]) - new_cfa_; \ |
151 |
(FS)->retaddr_column = CR0_REGNO; \ |
152 |
goto SUCCESS; \ |
153 |
} while (0) |
154 |
|