-
Notifications
You must be signed in to change notification settings - Fork 80
darwin syscall implementation is wrong #51
Comments
I'm looking at this now. In the asm_linux_amd64.ll version, we have this |
Nevermind, that appears to be the register parameter mapping and |
Really? I though "sideeffect" is just saying that the code may not be moved/optimised (think "volatile" in C). According to the ABI (PDF), we should have a clobber for
Thanks. |
Volatile in C means to me that the variable defined as such can be modified by another process/thread/hardware/etc. I've only ever used it with pointers meaning that the compiler can't just read the value into a register and keep using the register as the underlying value stored in memory could have been changed. In the same way the registers are volatile in the sense that after the call they might have changed and we can't trust that the value we put in them before the call are the same values after the call. http://llvm.org/docs/LangRef.html#inline-assembler-expressions says:
So the list after the instruction I read as the operand constraints list, especially due to the weird ordering of r10 which is called out as intentional in Go's asm_linux_amd64.s. And then the use of the sideeffect keyword I read as "volatile barrier" if I'm allowed to invent a new term ;) Do you know the motivation behind the -4095 constant? If I understand the code correctly this will make return values from -1 to -4094 fail and the rest pass. The man page just states that "The return value is defined by the system call being invoked. In general, a 0 return value indicates success. A -1 return value indicates an error, and an error code is stored in errno." Negative values from -1 to -4094 (or their uint64 equivalent) are unlikely to mean anything other than an error, but it would be good to know if there was any specific reason for choosing -4095 as the cut-off point of sane values specifically. |
I suggest taking a look at that PDF I linked, specifically section A.2.1. I think it'll answer your questions authoritatively.
Okay. The comment is regarding Linux AMD64 syscall vs. "standard" SysV AMD64 ABI. If you make a call to a C function, then rcx is used; if making a syscall, r10 in its place.
The code is saying: if the result is less than the unsigned representation of -4095, then everything's fine. Thus, if the result is between -1 and -4095, it's an error. This is described in the ABI document. If an error, the result == -errno, hence the sub instruction. The man page is referring to the C wrapper, which will be doing essentially the same as this function under the hood. |
I see, I'll amend the pull request with a link to the pdf and will correct the code comments. |
Btw, do you read the -4095 as being inclusive in the range that's an error? The doc states:
And currently we treat -1 as an error, but not -4095 due to the "less than" comparison. |
This change includes more links to reference material and now makes use of the carry flag to detect errors.
pkg/syscall: Fix darwin_amd64 syscalls. Fixes #51.
It's a bit subtle, but that -4095 is inclusive as it's an unsigned comparison. -4095 unsigned is 0xfffff001. The range -4095..-1 is 0xfffff001..0xffffffff. |
Ah, right you are :) |
See comments of #47
The text was updated successfully, but these errors were encountered: