tinycc-devel
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]