Commit a8c3320434cc0a7e8eaf3d58b56194f37d7441d3

Authored by pbrook
1 parent 1ffc346f

Update ARM non-rt sigframe layout.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4385 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 165 additions and 101 deletions
linux-user/signal.c
... ... @@ -1038,13 +1038,19 @@ struct target_ucontext_v2 {
1038 1038 abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));
1039 1039 };
1040 1040  
1041   -struct sigframe
  1041 +struct sigframe_v1
1042 1042 {
1043 1043 struct target_sigcontext sc;
1044 1044 abi_ulong extramask[TARGET_NSIG_WORDS-1];
1045 1045 abi_ulong retcode;
1046 1046 };
1047 1047  
  1048 +struct sigframe_v2
  1049 +{
  1050 + struct target_ucontext_v2 uc;
  1051 + abi_ulong retcode;
  1052 +};
  1053 +
1048 1054 struct rt_sigframe_v1
1049 1055 {
1050 1056 abi_ulong pinfo;
... ... @@ -1082,7 +1088,6 @@ static const abi_ulong retcodes[4] = {
1082 1088 };
1083 1089  
1084 1090  
1085   -#define __put_user_error(x,p,e) __put_user(x, p)
1086 1091 #define __get_user_error(x,p,e) __get_user(x, p)
1087 1092  
1088 1093 static inline int valid_user_regs(CPUState *regs)
... ... @@ -1090,38 +1095,34 @@ static inline int valid_user_regs(CPUState *regs)
1090 1095 return 1;
1091 1096 }
1092 1097  
1093   -static int
  1098 +static void
1094 1099 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
1095 1100 CPUState *env, abi_ulong mask)
1096 1101 {
1097   - int err = 0;
1098   -
1099   - __put_user_error(env->regs[0], &sc->arm_r0, err);
1100   - __put_user_error(env->regs[1], &sc->arm_r1, err);
1101   - __put_user_error(env->regs[2], &sc->arm_r2, err);
1102   - __put_user_error(env->regs[3], &sc->arm_r3, err);
1103   - __put_user_error(env->regs[4], &sc->arm_r4, err);
1104   - __put_user_error(env->regs[5], &sc->arm_r5, err);
1105   - __put_user_error(env->regs[6], &sc->arm_r6, err);
1106   - __put_user_error(env->regs[7], &sc->arm_r7, err);
1107   - __put_user_error(env->regs[8], &sc->arm_r8, err);
1108   - __put_user_error(env->regs[9], &sc->arm_r9, err);
1109   - __put_user_error(env->regs[10], &sc->arm_r10, err);
1110   - __put_user_error(env->regs[11], &sc->arm_fp, err);
1111   - __put_user_error(env->regs[12], &sc->arm_ip, err);
1112   - __put_user_error(env->regs[13], &sc->arm_sp, err);
1113   - __put_user_error(env->regs[14], &sc->arm_lr, err);
1114   - __put_user_error(env->regs[15], &sc->arm_pc, err);
  1102 + __put_user(env->regs[0], &sc->arm_r0);
  1103 + __put_user(env->regs[1], &sc->arm_r1);
  1104 + __put_user(env->regs[2], &sc->arm_r2);
  1105 + __put_user(env->regs[3], &sc->arm_r3);
  1106 + __put_user(env->regs[4], &sc->arm_r4);
  1107 + __put_user(env->regs[5], &sc->arm_r5);
  1108 + __put_user(env->regs[6], &sc->arm_r6);
  1109 + __put_user(env->regs[7], &sc->arm_r7);
  1110 + __put_user(env->regs[8], &sc->arm_r8);
  1111 + __put_user(env->regs[9], &sc->arm_r9);
  1112 + __put_user(env->regs[10], &sc->arm_r10);
  1113 + __put_user(env->regs[11], &sc->arm_fp);
  1114 + __put_user(env->regs[12], &sc->arm_ip);
  1115 + __put_user(env->regs[13], &sc->arm_sp);
  1116 + __put_user(env->regs[14], &sc->arm_lr);
  1117 + __put_user(env->regs[15], &sc->arm_pc);
1115 1118 #ifdef TARGET_CONFIG_CPU_32
1116   - __put_user_error(cpsr_read(env), &sc->arm_cpsr, err);
  1119 + __put_user(cpsr_read(env), &sc->arm_cpsr);
1117 1120 #endif
1118 1121  
1119   - __put_user_error(/* current->thread.trap_no */ 0, &sc->trap_no, err);
1120   - __put_user_error(/* current->thread.error_code */ 0, &sc->error_code, err);
1121   - __put_user_error(/* current->thread.address */ 0, &sc->fault_address, err);
1122   - __put_user_error(mask, &sc->oldmask, err);
1123   -
1124   - return err;
  1122 + __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
  1123 + __put_user(/* current->thread.error_code */ 0, &sc->error_code);
  1124 + __put_user(/* current->thread.address */ 0, &sc->fault_address);
  1125 + __put_user(mask, &sc->oldmask);
1125 1126 }
1126 1127  
1127 1128 static inline abi_ulong
... ... @@ -1180,31 +1181,78 @@ setup_return(CPUState *env, struct emulated_sigaction *ka,
1180 1181 return 0;
1181 1182 }
1182 1183  
  1184 +static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
  1185 + target_sigset_t *set, CPUState *env)
  1186 +{
  1187 + struct target_sigaltstack stack;
  1188 + int i;
  1189 +
  1190 + /* Clear all the bits of the ucontext we don't use. */
  1191 + memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
  1192 +
  1193 + memset(&stack, 0, sizeof(stack));
  1194 + __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
  1195 + __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
  1196 + __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
  1197 + memcpy(&uc->tuc_stack, &stack, sizeof(stack));
  1198 +
  1199 + setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);
  1200 + /* FIXME: Save coprocessor signal frame. */
  1201 + for(i = 0; i < TARGET_NSIG_WORDS; i++) {
  1202 + __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);
  1203 + }
  1204 +}
  1205 +
1183 1206 /* compare linux/arch/arm/kernel/signal.c:setup_frame() */
1184   -static void setup_frame(int usig, struct emulated_sigaction *ka,
1185   - target_sigset_t *set, CPUState *regs)
  1207 +static void setup_frame_v1(int usig, struct emulated_sigaction *ka,
  1208 + target_sigset_t *set, CPUState *regs)
1186 1209 {
1187   - struct sigframe *frame;
  1210 + struct sigframe_v1 *frame;
1188 1211 abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
1189   - int i, err = 0;
  1212 + int i;
1190 1213  
1191 1214 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1192 1215 return;
1193 1216  
1194   - err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
  1217 + setup_sigcontext(&frame->sc, regs, set->sig[0]);
1195 1218  
1196 1219 for(i = 1; i < TARGET_NSIG_WORDS; i++) {
1197 1220 if (__put_user(set->sig[i], &frame->extramask[i - 1]))
1198 1221 goto end;
1199 1222 }
1200 1223  
1201   - if (err == 0)
1202   - err = setup_return(regs, ka, &frame->retcode, frame_addr, usig,
1203   - frame_addr + offsetof(struct sigframe, retcode));
  1224 + setup_return(regs, ka, &frame->retcode, frame_addr, usig,
  1225 + frame_addr + offsetof(struct sigframe_v1, retcode));
1204 1226  
1205 1227 end:
1206 1228 unlock_user_struct(frame, frame_addr, 1);
1207   - // return err;
  1229 +}
  1230 +
  1231 +static void setup_frame_v2(int usig, struct emulated_sigaction *ka,
  1232 + target_sigset_t *set, CPUState *regs)
  1233 +{
  1234 + struct sigframe_v2 *frame;
  1235 + abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
  1236 +
  1237 + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
  1238 + return;
  1239 +
  1240 + setup_sigframe_v2(&frame->uc, set, regs);
  1241 +
  1242 + setup_return(regs, ka, &frame->retcode, frame_addr, usig,
  1243 + frame_addr + offsetof(struct sigframe_v2, retcode));
  1244 +
  1245 + unlock_user_struct(frame, frame_addr, 1);
  1246 +}
  1247 +
  1248 +static void setup_frame(int usig, struct emulated_sigaction *ka,
  1249 + target_sigset_t *set, CPUState *regs)
  1250 +{
  1251 + if (get_osversion() >= 0x020612) {
  1252 + setup_frame_v2(usig, ka, set, regs);
  1253 + } else {
  1254 + setup_frame_v1(usig, ka, set, regs);
  1255 + }
1208 1256 }
1209 1257  
1210 1258 /* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
... ... @@ -1215,17 +1263,17 @@ static void setup_rt_frame_v1(int usig, struct emulated_sigaction *ka,
1215 1263 struct rt_sigframe_v1 *frame;
1216 1264 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1217 1265 struct target_sigaltstack stack;
1218   - int i, err = 0;
  1266 + int i;
1219 1267 abi_ulong info_addr, uc_addr;
1220 1268  
1221 1269 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
1222 1270 return /* 1 */;
1223 1271  
1224 1272 info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
1225   - __put_user_error(info_addr, &frame->pinfo, err);
  1273 + __put_user(info_addr, &frame->pinfo);
1226 1274 uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
1227   - __put_user_error(uc_addr, &frame->puc, err);
1228   - err |= copy_siginfo_to_user(&frame->info, info);
  1275 + __put_user(uc_addr, &frame->puc);
  1276 + copy_siginfo_to_user(&frame->info, info);
1229 1277  
1230 1278 /* Clear all the bits of the ucontext we don't use. */
1231 1279 memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
... ... @@ -1236,26 +1284,20 @@ static void setup_rt_frame_v1(int usig, struct emulated_sigaction *ka,
1236 1284 __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1237 1285 memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
1238 1286  
1239   - err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/
1240   - env, set->sig[0]);
  1287 + setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
1241 1288 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1242 1289 if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
1243 1290 goto end;
1244 1291 }
1245 1292  
1246   - if (err == 0)
1247   - err = setup_return(env, ka, &frame->retcode, frame_addr, usig,
1248   - frame_addr + offsetof(struct rt_sigframe_v1, retcode));
  1293 + setup_return(env, ka, &frame->retcode, frame_addr, usig,
  1294 + frame_addr + offsetof(struct rt_sigframe_v1, retcode));
1249 1295  
1250   - if (err == 0) {
1251   - env->regs[1] = info_addr;
1252   - env->regs[2] = uc_addr;
1253   - }
  1296 + env->regs[1] = info_addr;
  1297 + env->regs[2] = uc_addr;
1254 1298  
1255 1299 end:
1256 1300 unlock_user_struct(frame, frame_addr, 1);
1257   -
1258   - // return err;
1259 1301 }
1260 1302  
1261 1303 static void setup_rt_frame_v2(int usig, struct emulated_sigaction *ka,
... ... @@ -1264,8 +1306,6 @@ static void setup_rt_frame_v2(int usig, struct emulated_sigaction *ka,
1264 1306 {
1265 1307 struct rt_sigframe_v2 *frame;
1266 1308 abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
1267   - struct target_sigaltstack stack;
1268   - int i, err = 0;
1269 1309 abi_ulong info_addr, uc_addr;
1270 1310  
1271 1311 if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
... ... @@ -1273,42 +1313,17 @@ static void setup_rt_frame_v2(int usig, struct emulated_sigaction *ka,
1273 1313  
1274 1314 info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
1275 1315 uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
1276   - err |= copy_siginfo_to_user(&frame->info, info);
  1316 + copy_siginfo_to_user(&frame->info, info);
1277 1317  
1278   - /* Clear all the bits of the ucontext we don't use. */
1279   - memset(&frame->uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
  1318 + setup_sigframe_v2(&frame->uc, set, env);
1280 1319  
1281   - memset(&stack, 0, sizeof(stack));
1282   - __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
1283   - __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
1284   - __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
1285   - memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
  1320 + setup_return(env, ka, &frame->retcode, frame_addr, usig,
  1321 + frame_addr + offsetof(struct rt_sigframe_v2, retcode));
1286 1322  
1287   - err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/
1288   - env, set->sig[0]);
1289   - for(i = 0; i < TARGET_NSIG_WORDS; i++) {
1290   - if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]))
1291   - goto end;
1292   - }
  1323 + env->regs[1] = info_addr;
  1324 + env->regs[2] = uc_addr;
1293 1325  
1294   - if (err == 0)
1295   - err = setup_return(env, ka, &frame->retcode, frame_addr, usig,
1296   - frame_addr + offsetof(struct rt_sigframe_v2, retcode));
1297   -
1298   - if (err == 0) {
1299   - /*
1300   - * For realtime signals we must also set the second and third
1301   - * arguments for the signal handler.
1302   - * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
1303   - */
1304   - env->regs[1] = info_addr;
1305   - env->regs[2] = uc_addr;
1306   - }
1307   -
1308   -end:
1309 1326 unlock_user_struct(frame, frame_addr, 1);
1310   -
1311   - // return err;
1312 1327 }
1313 1328  
1314 1329 static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
... ... @@ -1354,10 +1369,10 @@ restore_sigcontext(CPUState *env, struct target_sigcontext *sc)
1354 1369 return err;
1355 1370 }
1356 1371  
1357   -long do_sigreturn(CPUState *env)
  1372 +long do_sigreturn_v1(CPUState *env)
1358 1373 {
1359 1374 abi_ulong frame_addr;
1360   - struct sigframe *frame;
  1375 + struct sigframe_v1 *frame;
1361 1376 target_sigset_t set;
1362 1377 sigset_t host_set;
1363 1378 int i;
... ... @@ -1401,6 +1416,67 @@ badframe:
1401 1416 return 0;
1402 1417 }
1403 1418  
  1419 +static int do_sigframe_return_v2(CPUState *env, target_ulong frame_addr,
  1420 + struct target_ucontext_v2 *uc)
  1421 +{
  1422 + sigset_t host_set;
  1423 +
  1424 + target_to_host_sigset(&host_set, &uc->tuc_sigmask);
  1425 + sigprocmask(SIG_SETMASK, &host_set, NULL);
  1426 +
  1427 + if (restore_sigcontext(env, &uc->tuc_mcontext))
  1428 + return 1;
  1429 +
  1430 + if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
  1431 + return 1;
  1432 +
  1433 +#if 0
  1434 + /* Send SIGTRAP if we're single-stepping */
  1435 + if (ptrace_cancel_bpt(current))
  1436 + send_sig(SIGTRAP, current, 1);
  1437 +#endif
  1438 +
  1439 + return 0;
  1440 +}
  1441 +
  1442 +long do_sigreturn_v2(CPUState *env)
  1443 +{
  1444 + abi_ulong frame_addr;
  1445 + struct sigframe_v2 *frame;
  1446 +
  1447 + /*
  1448 + * Since we stacked the signal on a 64-bit boundary,
  1449 + * then 'sp' should be word aligned here. If it's
  1450 + * not, then the user is trying to mess with us.
  1451 + */
  1452 + if (env->regs[13] & 7)
  1453 + goto badframe;
  1454 +
  1455 + frame_addr = env->regs[13];
  1456 + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
  1457 + goto badframe;
  1458 +
  1459 + if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
  1460 + goto badframe;
  1461 +
  1462 + unlock_user_struct(frame, frame_addr, 0);
  1463 + return env->regs[0];
  1464 +
  1465 +badframe:
  1466 + unlock_user_struct(frame, frame_addr, 0);
  1467 + force_sig(SIGSEGV /* , current */);
  1468 + return 0;
  1469 +}
  1470 +
  1471 +long do_sigreturn(CPUState *env)
  1472 +{
  1473 + if (get_osversion() >= 0x020612) {
  1474 + return do_sigreturn_v2(env);
  1475 + } else {
  1476 + return do_sigreturn_v1(env);
  1477 + }
  1478 +}
  1479 +
1404 1480 long do_rt_sigreturn_v1(CPUState *env)
1405 1481 {
1406 1482 abi_ulong frame_addr;
... ... @@ -1446,7 +1522,6 @@ long do_rt_sigreturn_v2(CPUState *env)
1446 1522 {
1447 1523 abi_ulong frame_addr;
1448 1524 struct rt_sigframe_v2 *frame;
1449   - sigset_t host_set;
1450 1525  
1451 1526 /*
1452 1527 * Since we stacked the signal on a 64-bit boundary,
... ... @@ -1460,20 +1535,9 @@ long do_rt_sigreturn_v2(CPUState *env)
1460 1535 if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
1461 1536 goto badframe;
1462 1537  
1463   - target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
1464   - sigprocmask(SIG_SETMASK, &host_set, NULL);
1465   -
1466   - if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
1467   - goto badframe;
1468   -
1469   - if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v2, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
1470   - goto badframe;
  1538 + if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
  1539 + goto badframe;
1471 1540  
1472   -#if 0
1473   - /* Send SIGTRAP if we're single-stepping */
1474   - if (ptrace_cancel_bpt(current))
1475   - send_sig(SIGTRAP, current, 1);
1476   -#endif
1477 1541 unlock_user_struct(frame, frame_addr, 0);
1478 1542 return env->regs[0];
1479 1543  
... ...