[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Tinycc-devel] Incorrect function call code on ARMv6
From: |
Balazs Kezes |
Subject: |
[Tinycc-devel] Incorrect function call code on ARMv6 |
Date: |
Wed, 10 Aug 2016 06:59:46 +0100 |
User-agent: |
Mutt/1.5.24 (2015-08-30) |
Hi all!
I'm trying to use TCC on a raspberry pi but I'm running into issues:
$ cat callbug.c
#include <stdio.h>
void foo(long long x, int y) {
printf("x = %llx, y = %x\n", x, y);
}
int main(void) {
long long a1 = 0xdeadbeefcafebabeLL;
int a2 = 1;
long long *xx[] = { &a1 };
int *yy[] = { &a2 };
foo(**xx, **yy);
return 0;
}
$ tcc -c callbug.c && gcc callbug.o && ./a.out
x = deadbeefcafebabe, y = deadbeef
I'd expect it to print:
x = deadbeefcafebabe, y = 1
The problem is that TCC on the 32 bit ARM platform clobbers one of the
registers when setting up the registers for the function call. Here's
the disassembly of the above code:
$ objdump -d callbug.o
callbug.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <foo>:
0: e1a0c00d mov ip, sp
4: e92d000f push {r0, r1, r2, r3}
8: e92d5800 push {fp, ip, lr}
c: e1a0b00d mov fp, sp
10: e24bd004 sub sp, fp, #4
14: e24dd004 sub sp, sp, #4
18: e59b0014 ldr r0, [fp, #20]
1c: e52d0004 push {r0} ; (str r0, [sp, #-4]!)
20: e59b3010 ldr r3, [fp, #16]
24: e59b200c ldr r2, [fp, #12]
28: e59f0000 ldr r0, [pc] ; 30 <foo+0x30>
2c: ea000000 b 34 <foo+0x34>
30: 00000000 andeq r0, r0, r0
34: ebfffffe bl 0 <printf>
38: e28dd008 add sp, sp, #8
3c: e89ba800 ldm fp, {fp, sp, pc}
00000040 <main>:
40: e1a0c00d mov ip, sp
44: e92d5800 push {fp, ip, lr}
48: e1a0b00d mov fp, sp
4c: e24bd01c sub sp, fp, #28
50: e59f0000 ldr r0, [pc] ; 58 <main+0x18>
54: ea000000 b 5c <main+0x1c>
58: cafebabe bgt fffaeb58 <main+0xfffaeb18>
5c: e59f1000 ldr r1, [pc] ; 64 <main+0x24>
60: ea000000 b 68 <main+0x28>
64: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}
68: e50b0008 str r0, [fp, #-8]
6c: e50b1004 str r1, [fp, #-4]
70: e3a00001 mov r0, #1
74: e50b000c str r0, [fp, #-12]
78: e24b0008 sub r0, fp, #8
7c: e50b0010 str r0, [fp, #-16]
80: e24b000c sub r0, fp, #12
84: e50b0014 str r0, [fp, #-20]
88: e51b0010 ldr r0, [fp, #-16]
8c: e51b1014 ldr r1, [fp, #-20]
90: e5912000 ldr r2, [r1] ; <-- This is the y argument.
94: e50b2018 str r2, [fp, #-24]
98: e5901000 ldr r1, [r0]
9c: e2800004 add r0, r0, #4
a0: e5902000 ldr r2, [r0] ; <-- The clobbering happens here.
a4: e50b101c str r1, [fp, #-28]
a8: e1a01002 mov r1, r2
ac: e51b001c ldr r0, [fp, #-28]
b0: ebfffffe bl 0 <foo>
b4: e3a00000 mov r0, #0
b8: e1a00000 nop ; (mov r0, r0)
bc: e89ba800 ldm fp, {fp, sp, pc}
See my comments at 0x94 and 0xa0. That's where the problem happens. It
clobbers r2 because it uses r2 to dereference the long long pointer. I
don't think this bug affects other platforms: x86_64 already uses 64 bit
registers and i386 afaik uses stack to pass arguments so this cannot
happen.
I'm using the latest TCC:
$ git log -n 1 | cat
commit 0a402f6e91c284dd37cb61e726cc95de20fe895e
Author: David Mertens <address@hidden>
Date: Thu Aug 4 13:14:52 2016 -0400
Avoid conflicting definition for va_list on 64-bit Macs
$ uname -a
Linux eper 4.4.11-3-ARCH #1 Wed May 25 18:49:58 MDT 2016 armv6l GNU/Linux
$ ./configure --prefix=/usr
Binary directory /usr/bin
TinyCC directory /usr/lib/tcc
Library directory /usr/lib
Include directory /usr/include
Manual directory /usr/share/man
Info directory /usr/share/info
Doc directory /usr/share/doc
Target root prefix
Source path /home/rlblaster/proj/tcc/tinycc
C compiler gcc
ar ar
cross compilers no
Target CPU armv4l
Host OS Linux
Target OS Linux
Big Endian no
gprof enabled no
use libgcc no
Creating config.mak and config.h
config.h is unchanged
Can this be fixed? Thank you!
--
Balazs
- [Tinycc-devel] Incorrect function call code on ARMv6,
Balazs Kezes <=