I found that gcc 3.3.4/3.4.1 can not compile this sample code properly.
--- k.c ---
/* mips-linux-gcc -D__KERNEL__ -O2 -mno-abicalls -fno-pic -I $(KERNEL)/include
-S k.c */
#include <asm/uaccess.h>
extern char ptr[];
static int func0(int arg0)
{
return 0;
}
int func1(int *arg)
{
int arg0 = arg[0];
int arg1;
if (arg0)
return -1;
arg0 = func0(0);
get_user(arg1 , (int*)arg[1]);
if (func0(ptr[arg0]))
return 0;
if (arg1)
ptr[arg0] = 0;
return 0;
}
--- k.c end ---
The codes around the first calling of func0 are:
.set noreorder
.set nomacro
jal func0
.set macro
.set reorder
lw $4,4($16)
The jal does not have delay slot. Then "lw $4" (part of get_user)
executed as the delay slot instruction.
I create a sample code with very stripped version of get_user.
--- kk.c ---
/* mips-linux-gcc -O2 -mno-abicalls -fno-pic -S kk.c */
#define get_user(x,ptr) \
{ \
int __gu_val; \
__asm__ ("":"=r" (__gu_val)); \
if (ptr) { \
__asm__ __volatile__( \
"\tlw\t%0,%1\n\t" \
:"=r" (__gu_val) \
:"o" (*(ptr))); \
} \
(x) = __gu_val; \
}
extern char ptr[];
static int func0(int arg0)
{
return 0;
}
int func1(int *arg)
{
int arg0 = arg[0];
int arg1;
if (arg0)
return -1;
arg0 = func0(0);
get_user(arg1 , (int*)arg[1]);
if (func0(ptr[arg0]))
return 0;
if (arg1)
ptr[arg0] = 0;
return 0;
}
--- kk.c end ---
And complete output of gcc 3.3.4:
.file 1 "kk.c"
.section .mdebug.abi32
.previous
.text
.align 2
.ent func0
.type func0, @function
func0:
.frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, extra= 0
.mask 0x00000000,0
.fmask 0x00000000,0
.set noreorder
.set nomacro
j $31
move $2,$0
.set macro
.set reorder
.end func0
.align 2
.globl func1
.ent func1
.type func1, @function
func1:
.frame $sp,32,$31 # vars= 0, regs= 3/0, args= 16, extra= 0
.mask 0x80030000,-8
.fmask 0x00000000,0
subu $sp,$sp,32
sw $16,16($sp)
sw $31,24($sp)
move $16,$4
sw $17,20($sp)
lw $2,0($16)
move $4,$0
.set noreorder
.set nomacro
bne $2,$0,$L2
li $3,-1 # 0xffffffffffffffff
.set macro
.set reorder
.set noreorder
.set nomacro
jal func0
.set macro
.set reorder
lw $4,4($16)
#nop
beq $4,$0,$L4
#APP
lw $17,0($4)
#NO_APP
$L4:
la $16,ptr($2)
lb $4,0($16)
jal func0
.set noreorder
.set nomacro
bne $2,$0,$L2
move $3,$0
.set macro
.set reorder
beq $17,$0,$L2
sb $0,0($16)
$L2:
lw $31,24($sp)
lw $17,20($sp)
lw $16,16($sp)
move $2,$3
.set noreorder
.set nomacro
j $31
addu $sp,$sp,32
.set macro
.set reorder
.end func1
.ident "GCC: (GNU) 3.3.4"
Also complete output of gcc 3.4.1:
.file 1 "kk.c"
.section .mdebug.abi32
.previous
.text
.align 2
.ent func0
.type func0, @function
func0:
.frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0
.mask 0x00000000,0
.fmask 0x00000000,0
.set noreorder
.set nomacro
j $31
move $2,$0
.set macro
.set reorder
.end func0
.align 2
.globl func1
.ent func1
.type func1, @function
func1:
.frame $sp,32,$31 # vars= 0, regs= 3/0, args= 16, gp= 0
.mask 0x80030000,-8
.fmask 0x00000000,0
addiu $sp,$sp,-32
sw $16,16($sp)
sw $31,24($sp)
move $16,$4
sw $17,20($sp)
lw $3,0($16)
move $4,$0
.set noreorder
.set nomacro
bne $3,$0,$L2
li $5,-1 # 0xffffffffffffffff
.set macro
.set reorder
.set noreorder
.set nomacro
jal func0
.set macro
.set reorder
lw $4,4($16)
#nop
.set noreorder
.set nomacro
bne $4,$0,$L8
move $3,$2
.set macro
.set reorder
lui $2,%hi(ptr)
$L9:
addiu $2,$2,%lo(ptr)
addu $16,$3,$2
lb $4,0($16)
jal func0
.set noreorder
.set nomacro
bne $2,$0,$L2
move $5,$0
.set macro
.set reorder
beq $17,$0,$L2
sb $0,0($16)
$L2:
lw $31,24($sp)
lw $17,20($sp)
lw $16,16($sp)
move $2,$5
.set noreorder
.set nomacro
j $31
addiu $sp,$sp,32
.set macro
.set reorder
$L8:
#APP
lw $17,0($4)
#NO_APP
.set noreorder
.set nomacro
j $L9
lui $2,%hi(ptr)
.set macro
.set reorder
.end func1
.ident "GCC: (GNU) 3.4.1"
Is this a get_user's problem or gcc's?
---
Atsushi Nemoto
|