@@ -157,6 +157,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
157157{
158158 abi_ulong frame_addr ;
159159 struct target_rt_sigframe * frame ;
160+ int is_fdpic = info_is_fdpic (((TaskState * )thread_cpu -> opaque )-> info );
161+ abi_ulong handler = 0 ;
162+ abi_ulong handler_fdpic_GOT = 0 ;
160163 uint32_t ra ;
161164 bool abi_call0 ;
162165 unsigned base ;
@@ -165,6 +168,17 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
165168 frame_addr = get_sigframe (ka , env , sizeof (* frame ));
166169 trace_user_setup_rt_frame (env , frame_addr );
167170
171+ if (is_fdpic ) {
172+ abi_ulong funcdesc_ptr = ka -> _sa_handler ;
173+
174+ if (get_user_ual (handler , funcdesc_ptr )
175+ || get_user_ual (handler_fdpic_GOT , funcdesc_ptr + 4 )) {
176+ goto give_sigsegv ;
177+ }
178+ } else {
179+ handler = ka -> _sa_handler ;
180+ }
181+
168182 if (!lock_user_struct (VERIFY_WRITE , frame , frame_addr , 0 )) {
169183 goto give_sigsegv ;
170184 }
@@ -185,14 +199,21 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
185199 }
186200
187201 if (ka -> sa_flags & TARGET_SA_RESTORER ) {
188- ra = ka -> sa_restorer ;
202+ if (is_fdpic ) {
203+ if (get_user_ual (ra , ka -> sa_restorer )) {
204+ unlock_user_struct (frame , frame_addr , 0 );
205+ goto give_sigsegv ;
206+ }
207+ } else {
208+ ra = ka -> sa_restorer ;
209+ }
189210 } else {
190211 /* Not used, but retain for ABI compatibility. */
191212 install_sigtramp (frame -> retcode );
192213 ra = default_rt_sigreturn ;
193214 }
194215 memset (env -> regs , 0 , sizeof (env -> regs ));
195- env -> pc = ka -> _sa_handler ;
216+ env -> pc = handler ;
196217 env -> regs [1 ] = frame_addr ;
197218 env -> sregs [WINDOW_BASE ] = 0 ;
198219 env -> sregs [WINDOW_START ] = 1 ;
@@ -212,6 +233,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
212233 env -> regs [base + 3 ] = frame_addr + offsetof(struct target_rt_sigframe ,
213234 info );
214235 env -> regs [base + 4 ] = frame_addr + offsetof(struct target_rt_sigframe , uc );
236+ if (is_fdpic ) {
237+ env -> regs [base + 11 ] = handler_fdpic_GOT ;
238+ }
215239 unlock_user_struct (frame , frame_addr , 1 );
216240 return ;
217241
0 commit comments