- 论坛徽章:
- 0
|
做了一些试验,终于有所了解
1。__get_user_bad未定义
#define __get_user(x,ptr) \
__get_user_nocheck((x),(ptr),sizeof(*(ptr)))
#define __get_user_nocheck(x,ptr,size) \
({ \
long __gu_err, __gu_val; \
__get_user_size(__gu_val,(ptr),(size),__gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
#define __get_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
switch (size) { \
case 1: __get_user_asm(x,ptr,retval,"b","b","=q"); break; \
case 2: __get_user_asm(x,ptr,retval,"w","w","=r"); break; \
case 4: __get_user_asm(x,ptr,retval,"l","","=r"); break; \
default: (x) = __get_user_bad(); \
} \
} while (0)
可知在传给__get_user_size(x,ptr,size,retval) 的参数中,size是个常量
如果这个常量等于1的话,那么宏__get_user_size(x,ptr,size,retval)就被替代优化为
retval=0;
__get_user_asm(x,ptr,retval,"b","b","=q");
注意最终的代码中没有调用__get_user_bad()
2,4同理
如果是其它的值的话,就被替代优化为
retval=0;
(x) = __get_user_bad();
最后连接时可想而知,报错:未知的外部连接。这就提醒了程序员有错误的调用发生
2。__m宏的问题
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
#define __get_user_asm(x, addr, err, itype, rtype, ltype) \
__asm__ __volatile__( \
"1: mov"itype" %2,%"rtype"1\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3: movl %3,%0\n" \
" xor"itype" %"rtype"1,%"rtype"1\n"\
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 1b,3b\n" \
".previous" \
: "=r"(err), ltype (x) \
: "m"(__m(addr)), "i"(-EFAULT), "0"(err))
宏的意图是x=*addr
如果写成"m"(addr),则变成x=addr,显然是错误的
如果写成"m"(*addr),则变成x=*addr(经试验是正确的)
而上面写的是"m"(*(struct __large_struct *)(addr)),多了一个类型强制转换(不知是何用意) |
|