Closed
Bug 633436
Opened 14 years ago
Closed 14 years ago
Android (thumb) debug builds are broken
Categories
(Toolkit :: Crash Reporting, defect)
Tracking
()
RESOLVED
FIXED
People
(Reporter: cjones, Assigned: cjones)
References
Details
Attachments
(2 files)
1.14 KB,
patch
|
vlad
:
review+
benjamin
:
approval2.0+
|
Details | Diff | Splinter Review |
1.53 KB,
patch
|
cjones
:
review+
|
Details | Diff | Splinter Review |
/home/cjones/mozilla/mozilla-central/toolkit/crashreporter/google-breakpad/src/client/linux/handler/../../../common/linux/linux_syscall_support.h: In function 'int sys_clone(int (*)(void*), void*, int, void*, int*, void*, int*)':
/home/cjones/mozilla/mozilla-central/toolkit/crashreporter/google-breakpad/src/client/linux/handler/../../../common/linux/linux_syscall_support.h:2202: error: r7 cannot be used in asm here
Assignee | ||
Comment 1•14 years ago
|
||
r?->vlad on blassey's advice.
The comment in the patch describes the problem. I'm not sure if I need to save r7 here or I can rely on this function being inlined and the caller's save of r7.
Assignee: nobody → jones.chris.g
Attachment #511638 -
Flags: review?(vladimir)
Assignee | ||
Comment 2•14 years ago
|
||
The code causing the error is
LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
int flags, void *arg, int *parent_tidptr,
void *newtls, int *child_tidptr) {
long __res;
__asm__ __volatile__(/* if (fn == NULL)
* return -EINVAL;
*/
"movl %3,%%ecx\n"
"jecxz 1f\n"
/* if (child_stack == NULL)
* return -EINVAL;
*/
"movl %4,%%ecx\n"
"jecxz 1f\n"
/* Set up alignment of the child stack:
* child_stack = (child_stack & ~0xF) - 20;
*/
"andl $-16,%%ecx\n"
"subl $20,%%ecx\n"
/* Push "arg" and "fn" onto the stack that will be
* used by the child.
*/
"movl %6,%%eax\n"
"movl %%eax,4(%%ecx)\n"
"movl %3,%%eax\n"
"movl %%eax,(%%ecx)\n"
/* %eax = syscall(%eax = __NR_clone,
* %ebx = flags,
* %ecx = child_stack,
* %edx = parent_tidptr,
* %esi = newtls,
* %edi = child_tidptr)
* Also, make sure that %ebx gets preserved as it is
* used in PIC mode.
*/
"movl %8,%%esi\n"
"movl %7,%%edx\n"
"movl %5,%%eax\n"
"movl %9,%%edi\n"
"pushl %%ebx\n"
"movl %%eax,%%ebx\n"
"movl %2,%%eax\n"
LSS_ENTRYPOINT
/* In the parent: restore %ebx
* In the child: move "fn" into %ebx
*/
"popl %%ebx\n"
/* if (%eax != 0)
* return %eax;
*/
"test %%eax,%%eax\n"
"jnz 1f\n"
/* In the child, now. Terminate frame pointer chain.
*/
"movl $0,%%ebp\n"
/* Call "fn". "arg" is already on the stack.
*/
"call *%%ebx\n"
/* Call _exit(%ebx). Unfortunately older versions
* of gcc restrict the number of arguments that can
* be passed to asm(). So, we need to hard-code the
* system call number.
*/
"movl %%eax,%%ebx\n"
"movl $1,%%eax\n"
LSS_ENTRYPOINT
/* Return to parent.
*/
"1:\n"
: "=a" (__res)
: "0"(-EINVAL), "i"(__NR_clone),
"m"(fn), "m"(child_stack), "m"(flags), "m"(arg),
"m"(parent_tidptr), "m"(newtls), "m"(child_tidptr)
: "esp", "memory", "ecx", "edx", "esi", "edi");
LSS_RETURN(int, __res);
}
Assignee | ||
Comment 3•14 years ago
|
||
Comment on attachment 511638 [details] [diff] [review]
Fix register conflict
Nm, I do need to store r7 here.
Attachment #511638 -
Attachment is obsolete: true
Attachment #511638 -
Flags: review?(vladimir)
Assignee | ||
Updated•14 years ago
|
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → DUPLICATE
Assignee | ||
Updated•14 years ago
|
Status: RESOLVED → REOPENED
Resolution: DUPLICATE → ---
Assignee | ||
Comment 5•14 years ago
|
||
Comment on attachment 511638 [details] [diff] [review]
Fix register conflict
The existing code is already marking r7 as a clobbered register, so it should be OK. (God I hate inline assembly.)
Attachment #511638 -
Attachment is obsolete: false
Attachment #511638 -
Flags: review?(vladimir)
Assignee | ||
Comment 6•14 years ago
|
||
(In reply to comment #2)
> The code causing the error is
... and that's totally the x86 code. Should read before I copypaste. Here's what I meant to post.
LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
int flags, void *arg, int *parent_tidptr,
void *newtls, int *child_tidptr) {
long __res;
{
register int __flags __asm__("r0") = flags;
register void *__stack __asm__("r1") = child_stack;
register void *__ptid __asm__("r2") = parent_tidptr;
register void *__tls __asm__("r3") = newtls;
register int *__ctid __asm__("r4") = child_tidptr;
__asm__ __volatile__(/* if (fn == NULL || child_stack == NULL)
* return -EINVAL;
*/
"cmp %2,#0\n"
"it ne\n"
"cmpne %3,#0\n"
"it eq\n"
"moveq %0,%1\n"
"beq 1f\n"
/* Push "arg" and "fn" onto the stack that will be
* used by the child.
*/
"str %5,[%3,#-4]!\n"
"str %2,[%3,#-4]!\n"
/* %r0 = syscall(%r0 = flags,
* %r1 = child_stack,
* %r2 = parent_tidptr,
* %r3 = newtls,
* %r4 = child_tidptr)
*/
"mov r7, %9\n"
"swi 0x0\n"
/* if (%r0 != 0)
* return %r0;
*/
"movs %0,r0\n"
"bne 1f\n"
/* In the child, now. Call "fn(arg)".
*/
"ldr r0,[sp, #4]\n"
"mov lr,pc\n"
"ldr pc,[sp]\n"
/* Call _exit(%r0).
*/
"mov r7, %10\n"
"swi 0x0\n"
"1:\n"
: "=r" (__res)
: "i"(-EINVAL),
"r"(fn), "r"(__stack), "r"(__flags), "r"(arg),
"r"(__ptid), "r"(__tls), "r"(__ctid),
"i"(__NR_clone), "i"(__NR_exit)
: "cc", "r7", "lr", "memory");
}
LSS_RETURN(int, __res);
}
Comment on attachment 511638 [details] [diff] [review]
Fix register conflict
I guess this is ok, but it's a little weird that it's broken!
Attachment #511638 -
Flags: review?(vladimir) → review+
Assignee | ||
Comment 8•14 years ago
|
||
FWIW, I think this is a gcc bug. The generic syscall template, LSS_BODY, writes to r7 but pushes/pops it, and gcc doesn't complain about that. Seems like it treats clobbered registers differently, or maybe it's being smarter than we're giving it credit for. I dunno.
Assignee | ||
Comment 9•14 years ago
|
||
Comment on attachment 511638 [details] [diff] [review]
Fix register conflict
Would like to land this to unbork android debug builds. We don't really care so much about breakpad in debug builds, so if it's wonky it's not on anyone's critical path to fix it.
Attachment #511638 -
Flags: approval2.0?
Assignee | ||
Comment 10•14 years ago
|
||
Also, exception_handler.s sez
sys_clone:
.LFB1131:
.file 8 "/home/cjones/mozilla/mozilla-central/toolkit/crashreporter/google-breakpad/src/client/linux/handler/../../../common/linux/linux_syscall_support.h"
.loc 8 2144 0
@ args = 12, pretend = 0, frame = 24
@ frame_needed = 0, uses_anonymous_args = 0
push {r4, r5, r7, lr}
[snip]
pop {r4, r5, r7, pc}
.LFE1131:
.size sys_clone, .-sys_clone
so the generated assembly is doing the right thing.
Assignee | ||
Comment 11•14 years ago
|
||
Attachment #511666 -
Flags: review+
Comment 13•14 years ago
|
||
That file has its own SVN repo, if you can give me a patch against that repo I'll ferry this upstream for you:
http://code.google.com/p/linux-syscall-support/
Comment 14•14 years ago
|
||
Oh, ick, it's a Makefile patch. :-( There's really no legitimate way to fix this, eh?
Assignee | ||
Comment 15•14 years ago
|
||
Well, there's no bug to "fix" on our side, AFAICT. I put what I know in the Makefile comment
+# The syscall number is passed through r7 in the linux ARM ABI, but r7
+# is also the THUMB frame pointer. (Unfortunate, but ah well.) gcc
+# complains if we store to r7, not unreasonably, but complains
+# inconsistently. The generic syscall template pushes/stores to/pops
+# r7 with no complaint from gcc, but the sys_clone() function marks r7
+# as a clobbered register yet gcc error's. The generated assembly for
+# sys_clone() looks OK, so we chalk this up to a gcc/gas quirk and
+# work around it by telling gcc that the THUMB frame pointer is a
+# vanilla callee-save register.
I'm about 90% sure gcc is either being weird or being very smart.
Updated•14 years ago
|
Attachment #511638 -
Flags: approval2.0? → approval2.0+
Assignee | ||
Comment 16•14 years ago
|
||
Status: REOPENED → RESOLVED
Closed: 14 years ago → 14 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•