[prev in list] [next in list] [prev in thread] [next in thread]
List: gcc-bugs
Subject: [Bug sanitizer/86755] New: [ASAN] Libasan failed to be build for arm with -mthumb and -fno-omit-fram
From: "d.khalikov at partner dot samsung.com" <gcc-bugzilla () gcc ! gnu ! org>
Date: 2018-07-31 15:46:53
Message-ID: bug-86755-4 () http ! gcc ! gnu ! org/bugzilla/
[Download RAW message or body]
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86755
Bug ID: 86755
Summary: [ASAN] Libasan failed to be build for arm with -mthumb
and -fno-omit-frame-pointer
Product: gcc
Version: 9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: sanitizer
Assignee: unassigned at gcc dot gnu.org
Reporter: d.khalikov at partner dot samsung.com
CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at gcc dot gnu.org
Target Milestone: ---
Created attachment 44471
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44471&action=edit
Reduced test case
GCC fails to build libasan with -mthumb and -fno-omit-frame-pointer
../../../../libsanitizer/sanitizer_common/sanitizer_linux.cc: In function
'__sanitizer::uptr __sanitizer::internal_clone(int (*)(void*), void*, int,
void*, int*, void*, int*)':
../../../../libsanitizer/sanitizer_common/sanitizer_linux.cc:1540:1: error: r7
cannot be used in asm here
}
The problem is inside internal_clone function defined for arm.
Reduced test case:
$cat clone.cc
#define __NR_clone 120
#define __NR_exit 1
using uptr = unsigned int;
unsigned int EINVAL = 1;
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
int *parent_tidptr, void *newtls, int *child_tidptr) {
unsigned int res;
if (!fn || !child_stack)
return -EINVAL;
child_stack = (char *)child_stack - 2 * sizeof(unsigned int);
((unsigned int *)child_stack)[0] = (uptr)fn;
((unsigned int *)child_stack)[1] = (uptr)arg;
register int r0 __asm__("r0") = flags;
register void *r1 __asm__("r1") = child_stack;
register int *r2 __asm__("r2") = parent_tidptr;
register void *r3 __asm__("r3") = newtls;
register int *r4 __asm__("r4") = child_tidptr;
register int r7 __asm__("r7") = __NR_clone;
#if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__)
# define ARCH_HAS_BX
#endif
#if __ARM_ARCH > 4
# define ARCH_HAS_BLX
#endif
#ifdef ARCH_HAS_BX
# ifdef ARCH_HAS_BLX
# define BLX(R) "blx " #R "\n"
# else
# define BLX(R) "mov lr, pc; bx " #R "\n"
# endif
#else
# define BLX(R) "mov lr, pc; mov pc," #R "\n"
#endif
__asm__ __volatile__(
/* %r0 = syscall(%r7 = SYSCALL(clone),
* %r0 = flags,
* %r1 = child_stack,
* %r2 = parent_tidptr,
* %r3 = new_tls,
* %r4 = child_tidptr)
*/
/* Do the system call */
"swi 0x0\n"
/* if (%r0 != 0)
* return %r0;
*/
"cmp r0, #0\n"
"bne 1f\n"
/* In the child, now. Call "fn(arg)". */
"ldr r0, [sp, #4]\n"
"ldr ip, [sp], #8\n"
BLX(ip)
/* Call _exit(%r0). */
"mov r7, %7\n"
"swi 0x0\n"
"1:\n"
"mov %0, r0\n"
: "=r"(res)
: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7),
"i"(__NR_exit)
: "memory");
return res;
}
$armv7l-linux-gnueabi-g++ -o clone.s clone.cc -fno-omit-frame-pointer -mthumb
-S
clone.cc: In function ‘uptr internal_clone(int (*)(void*), void*, int, void*,
int*, void*, int*)':
clone.cc:70:1: error: r7 cannot be used in asm here
Regarding to arm ABI, r7 register is using for syscall number, r0 for return
value, and r1 - r6 for syscall arguments, by the way r7 for arm with THUMB2
mode is using as frame pointer and it looks like we have a conflict in this
case. As far as I understood, GCC has a special check inside IRA
if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM)), which
does not allow to have frame pointer register as clobber register.
In other way, there is no issue with clang:
clang++ -target armv7l -S -o clone.s clone.cc -mthumb -fno-omit-frame-pointer
So, looks like we can save syscall number in r8 register, move it to r7 before
we the interruption, and restore the value in the parent task.
register int r8 __asm__("r8") = __NR_clone;
__asm__ __volatile__(
/* %r0 = syscall(%r7 = SYSCALL(clone),
* %r0 = flags,
* %r1 = child_stack,
* %r2 = parent_tidptr,
* %r3 = new_tls,
* %r4 = child_tidptr)
*/
"push {r7}\n"
"mov r7, r8\n"
/* Do the system call */
"swi 0x0\n"
/* if (%r0 != 0)
* return %r0;
*/
"cmp r0, #0\n"
"bne 1f\n"
/* In the child, now. Call "fn(arg)". */
"ldr r0, [sp, #4]\n"
"ldr ip, [sp], #8\n"
BLX(ip)
/* Call _exit(%r0). */
"mov r7, %7\n"
"swi 0x0\n"
"1:\n"
"pop {r7}\n"
"mov %0, r0\n"
: "=r"(res)
: "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r8),
"i"(__NR_exit)
: "memory");
return res;
}=
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic