AOSP非显而易见的syscall()实现 [英] AOSP non-obvious syscall() implementation
问题描述
据我所知,Linux ABI for ARM指出syscall返回值是通过r0
传递的,如果它是负数,则应将其作为errno值的取反值进行处理.即syscall结束时出现了一些错误.
AOSP 进行此检查以某种奇特的方式:
As far as I know Linux ABI for ARM states that syscall return value is passed via r0
and if it is negative it should be threaded as errno value negated. I.e syscall has ended up with some error.
AOSP does this check in some fancy way:
ENTRY(syscall)
mov ip, sp
stmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 16
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
mov r7, r0
mov r0, r1
mov r1, r2
mov r2, r3
ldmfd ip, {r3, r4, r5, r6}
swi #0
ldmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 0
cmn r0, #(MAX_ERRNO + 1) /* Set C flag if r0 is between -4095 and -1, set Z flag if r0 == -4096 */
bxls lr /* return if Z is set or C is clear */
neg r0, r0
b __set_errno_internal
END(syscall)
看起来该函数不会威胁r0 < -4096
作为错误条件.虽然应该.当然,真正的errno
将适合允许的差距,但是无论如何,以这种方式执行检查而不是仅仅测试r0
的负性是什么原理?
Looks like this function won't threat r0 < -4096
as error condition. While it should. Of course real errno
will fit into allowed gap, but anyway what was rationale to perform check in that way instead of just testing r0
for negativity?
P.S.如果我错过了某些事情,或者只是我的分析不正确-任何评论都值得赞赏.
P.S. If I've missed something or just my analysis is incorrect - any comments appreciated.
推荐答案
errno值的Apper限制4095是有意的,并且可以在代码中使用此知识.实际上,这会将值模型修改,通过系统调用和其他一些内核函数返回,以:
Apper limit 4095 for errno value is intentional, and using this knowledge in the code is fine. Practically, this modifies model of value, returning by syscalls and some other kernel functions, to:
-
[-4095 ... -1]
-错误 - 其他值-结果
[-4095 ... -1]
- error- other values - result
此模型允许更多可能的结果值.例如,如果将结果解释为无符号长整数,则结果的值范围将从[0... (MAX/2)]
扩展到[0 ... (MAX - 4096)]
.这很有用,例如当结果是指针时,请参见实现IS_ERR
宏的a>.
This model allows more possible values for result. E.g., if interpret result as unsigned long integer, then value's range for result is extended from [0... (MAX/2)]
to [0 ... (MAX - 4096)]
. This is useful, e.g. when result is a pointer, see implementation of IS_ERR
macro.
这篇关于AOSP非显而易见的syscall()实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!