aarch64: workaround gcc+kernel bug
Due to a subtle gcc bug that leads to miscompiled aarch64 kernels, the 3rd argument of sched_getattr syscall is not quite 32-bit on aarch64 as on other architectures. For more details see https://sourceforge.net/p/strace/mailman/message/35721703/ * defs.h (print_abnormal_hi): New prototype. * util.c (print_abnormal_hi): New function. * sched.c (SYS_FUNC(sched_getattr)) [AARCH64]: Use it. * tests/sched_xetattr.c (main) [__arm64__ || __aarch64__]: Test it.
This commit is contained in:
parent
5b7681cf05
commit
a8d2417e97
1
defs.h
1
defs.h
@ -550,6 +550,7 @@ extern void print_symbolic_mode_t(unsigned int);
|
||||
extern void print_numeric_umode_t(unsigned short);
|
||||
extern void print_numeric_long_umask(unsigned long);
|
||||
extern void print_dev_t(unsigned long long dev);
|
||||
extern void print_abnormal_hi(kernel_ulong_t);
|
||||
|
||||
extern void
|
||||
dumpiov_in_msghdr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t data_size);
|
||||
|
14
sched.c
14
sched.c
@ -176,7 +176,19 @@ SYS_FUNC(sched_getattr)
|
||||
print_sched_attr(tcp, tcp->u_arg[1], size);
|
||||
else
|
||||
printaddr(tcp->u_arg[1]);
|
||||
tprintf(", %u, %u", size, (unsigned int) tcp->u_arg[3]);
|
||||
tprints(", ");
|
||||
#ifdef AARCH64
|
||||
/*
|
||||
* Due to a subtle gcc bug that leads to miscompiled aarch64
|
||||
* kernels, the 3rd argument of sched_getattr is not quite 32-bit
|
||||
* as on other architectures. For more details see
|
||||
* https://sourceforge.net/p/strace/mailman/message/35721703/
|
||||
*/
|
||||
if (syserror(tcp))
|
||||
print_abnormal_hi(tcp->u_arg[2]);
|
||||
#endif
|
||||
tprintf("%u", size);
|
||||
tprintf(", %u", (unsigned int) tcp->u_arg[3]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -81,8 +81,14 @@ main(void)
|
||||
printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr);
|
||||
|
||||
sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags);
|
||||
printf("sched_getattr(-1, %p, %u, %u) = %s\n",
|
||||
attr, (unsigned) bogus_size, (unsigned) bogus_flags, errstr);
|
||||
printf("sched_getattr(-1, %p, %s%u, %u) = %s\n",
|
||||
attr,
|
||||
# if defined __arm64__ || defined __aarch64__
|
||||
"0xdefaced<<32|",
|
||||
# else
|
||||
"",
|
||||
# endif
|
||||
(unsigned) bogus_size, (unsigned) bogus_flags, errstr);
|
||||
|
||||
sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0);
|
||||
printf("sched_getattr(0, %p, %u, 0) = %s\n",
|
||||
@ -103,20 +109,31 @@ main(void)
|
||||
attr->sched_period,
|
||||
(unsigned) sizeof(*attr));
|
||||
|
||||
# if defined __arm64__ || defined __aarch64__
|
||||
long rc =
|
||||
# endif
|
||||
sys_sched_getattr(F8ILL_KULONG_MASK, (unsigned long) attr,
|
||||
F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK);
|
||||
printf("sched_getattr(0, {size=%u, sched_policy=", attr->size);
|
||||
printxval(schedulers, attr->sched_policy, NULL);
|
||||
printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
|
||||
", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
|
||||
", sched_period=%" PRIu64 "}, %u, 0) = 0\n",
|
||||
attr->sched_flags ? "SCHED_FLAG_RESET_ON_FORK" : "0",
|
||||
attr->sched_nice,
|
||||
attr->sched_priority,
|
||||
attr->sched_runtime,
|
||||
attr->sched_deadline,
|
||||
attr->sched_period,
|
||||
(unsigned) sizeof(*attr));
|
||||
# if defined __arm64__ || defined __aarch64__
|
||||
if (rc) {
|
||||
printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n",
|
||||
attr, (unsigned) sizeof(*attr), errstr);
|
||||
} else
|
||||
# endif
|
||||
{
|
||||
printf("sched_getattr(0, {size=%u, sched_policy=", attr->size);
|
||||
printxval(schedulers, attr->sched_policy, NULL);
|
||||
printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
|
||||
", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
|
||||
", sched_period=%" PRIu64 "}, %u, 0) = 0\n",
|
||||
attr->sched_flags ? "SCHED_FLAG_RESET_ON_FORK" : "0",
|
||||
attr->sched_nice,
|
||||
attr->sched_priority,
|
||||
attr->sched_runtime,
|
||||
attr->sched_deadline,
|
||||
attr->sched_period,
|
||||
(unsigned) sizeof(*attr));
|
||||
}
|
||||
|
||||
sys_sched_setattr(bogus_pid, 0, 0);
|
||||
printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr);
|
||||
|
11
util.c
11
util.c
@ -1535,6 +1535,17 @@ printargs_d(struct tcb *tcp)
|
||||
return RVAL_DECODED;
|
||||
}
|
||||
|
||||
/* Print abnormal high bits of a kernel_ulong_t value. */
|
||||
void
|
||||
print_abnormal_hi(const kernel_ulong_t val)
|
||||
{
|
||||
if (current_klongsize > 4) {
|
||||
const unsigned int hi = (unsigned int) ((uint64_t) val >> 32);
|
||||
if (hi)
|
||||
tprintf("%#x<<32|", hi);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined _LARGEFILE64_SOURCE && defined HAVE_OPEN64
|
||||
# define open_file open64
|
||||
#else
|
||||
|
Loading…
x
Reference in New Issue
Block a user