Mips ABI specifies to let the space for 4 arguments in stack when calling a
function. This is not respected when accessing tls variable with a dynamic
model: gcc implicitely calls __get_tls_addr without making rooms for the
arguments. The top of the stack is then likely to be erase.
Here is an example:

- test.c:

extern void* __get_tls_addr(void*);
extern __thread int a;
void func(void)
{
    a++;
}

Compiled and linked with:

mipsel-unknown-elf-gcc -fpic -mshared -nostdinc -nostdlib -fno-builtin -mips2
-EL -mabicalls -G0 -c -o test.o test.c
mipsel-unknown-elf-ld -shared test.o -o test.so

Result in assembly:

5ffe0390 <func>:
5ffe0390:       3c1c0001        lui     gp,0x1
5ffe0394:       279c9090        addiu   gp,gp,-28528
5ffe0398:       0399e021        addu    gp,gp,t9
5ffe039c:       27bdffe8        addiu   sp,sp,-24
5ffe03a0:       afbf0014        sw      ra,20(sp)
5ffe03a4:       afbe0010        sw      s8,16(sp)
5ffe03a8:       afb0000c        sw      s0,12(sp)
5ffe03ac:       03a0f021        move    s8,sp
5ffe03b0:       afbc0000        sw      gp,0(sp)
5ffe03b4:       8f99802c        lw      t9,-32724(gp)
5ffe03b8:       27848030        addiu   a0,gp,-32720
5ffe03bc:       0320f809        jalr    t9
5ffe03c0:       00000000        nop
5ffe03c4:       8fdc0000        lw      gp,0(s8)
5ffe03c8:       8c420000        lw      v0,0(v0)
...

We can see than $gp is saved directly at the top of the stack 0($sp), and is
likely to be erase in the callee function.

A temporarily workaround is to insert a real function call in the same function
which uses a tls variable.
Example:

extern void* __get_tls_addr(void*);
extern __thread int a;
static inline void fake(void){}
void func(void)
{
    fake();
    a++;
}

This result is then:
5ffe0390 <func>:
5ffe0390:       3c1c0001        lui     gp,0x1
5ffe0394:       279c90c0        addiu   gp,gp,-28480
5ffe0398:       0399e021        addu    gp,gp,t9
5ffe039c:       27bdffd8        addiu   sp,sp,-40
5ffe03a0:       afbf0024        sw      ra,36(sp)
5ffe03a4:       afbe0020        sw      s8,32(sp)
5ffe03a8:       afb0001c        sw      s0,28(sp)
5ffe03ac:       03a0f021        move    s8,sp
5ffe03b0:       afbc0010        sw      gp,16(sp)
5ffe03b4:       8f828018        lw      v0,-32744(gp)
5ffe03b8:       24590418        addiu   t9,v0,1048
5ffe03bc:       0320f809        jalr    t9
5ffe03c0:       00000000        nop
5ffe03c4:       8fdc0010        lw      gp,16(s8)
...

We can now see that $gp is stored at 16($sp), which gives the required spare
space for the 4 arguments in stack.


-- 
           Summary: [Mips] No space for arguments when implicitely calling
                    __get_tls_addr
           Product: gcc
           Version: 4.3.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: joel dot porquet at gmail dot com
  GCC host triplet: i486-linux-gnu
GCC target triplet: mipsel-unknown-elf


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39493

Reply via email to