2016-08-03 10 views
3

ist Go's undocumented Syscall function:Was ist der zweite `r2` Rückgabewert in Gos Syscall() für? Hier

func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 

Und hier ist the C definition:

long syscall(long number, ...); 

recht unterschiedlich. Es ist also ziemlich offensichtlich, dass trapnumber ist, und a1, a2 und a3 für drei Argumente zulassen. Ich habe auch herausgefunden, dass r1 der Rückgabewert ist und errerrno ist. Aber was ist r2? Die Syscall-Man-Seite erwähnt mehrere Rückgabewerte nicht.

Es tut den tatsächlichen Aufrufkonventionen geben (noch nur ein Retval):

 arch/ABI instruction   syscall # retval error Notes 
     ──────────────────────────────────────────────────────────────────── 
     alpha  callsys    v0   a0  a3  [1] 
     arc   trap0     r8   r0  - 
     arm/OABI swi NR    -   a1  -  [2] 
     arm/EABI swi 0x0    r7   r0  - 
     arm64  svC#0    x8   x0  - 
     blackfin excpt 0x0    P0   R0  - 
     i386  int $0x80    eax  eax  - 
     ia64  break 0x100000  r15  r8  r10  [1] 
     m68k  trap #0    d0   d0  - 
     microblaze brki r14,8   r12  r3  - 
     mips  syscall    v0   v0  a3  [1] 
     nios2  trap     r2   r2  r7 
     parisc  ble 0x100(%sr2, %r0) r20  r28  - 
     powerpc  sc     r0   r3  r0  [1] 
     s390  svc 0     r1   r2  -  [3] 
     s390x  svc 0     r1   r2  -  [3] 
     superh  trap #0x17   r3   r0  -  [4] 
     sparc/32 t 0x10    g1   o0  psr/csr [1] 
     sparc/64 t 0x6d    g1   o0  psr/csr [1] 
     tile  swint1    R10  R00  R01  [1] 
     x86_64  syscall    rax  rax  -  [5] 
     x32   syscall    rax  rax  -  [5] 
     xtensa  syscall    a2   a2  - 

aber auf x86 dies the implementation

#define INVOKE_SYSCALL INT $0x80 

    TEXT ·Syscall(SB),NOSPLIT,$0-28 
     CALL runtime·entersyscall(SB) 
     MOVL trap+0(FP), AX // syscall entry 
     MOVL a1+4(FP), BX 
     MOVL a2+8(FP), CX 
     MOVL a3+12(FP), DX 
     MOVL $0, SI 
     MOVL $0, DI 
     INVOKE_SYSCALL 
     CMPL AX, $0xfffff001 
     JLS ok 
     MOVL $-1, r1+16(FP) 
     MOVL $0, r2+20(FP) 
     NEGL AX 
     MOVL AX, err+24(FP) 
     CALL runtime·exitsyscall(SB) 
     RET 
    ok: 
     MOVL AX, r1+16(FP) 
     MOVL DX, r2+20(FP) 
     MOVL $0, err+24(FP) 
     CALL runtime·exitsyscall(SB) 
     RET 

Nun, ich lese nicht Versammlung zu gut, aber Ich bin mir ziemlich sicher, dass EDX in R2 zurückgegeben wird. Warum?

Antwort

4

Ich denke, sie haben mehrere Rückgabewerte für die Konsistenz. Wie Sie aus dieser Tabelle sehen können, geben einige Architekturen mehrere Werte zurück, und wenn Sie einige der anderen Assemblydateien aus diesem Verzeichnis überprüfen, sehen Sie, dass sie die Registerwerte auf r2 verschieben.


Aber warum DX? Dieser Teil ist immer noch rätselhaft. Über das Web verstreut sind Dokumente, die auf i386 erwähnen, dass eine Funktion sowohl EAX als auch EDX für Rückgabewerte verwenden darf. Zum Beispiel System V Application Binary Interface Intel386 Architecture Processor Supplement:

% EDX scratch Register; auch

später die oberen 32 Bit einiger 64-Bit-Rückgabetypen verwendet zurück geht es weiter:

Die wichtigsten 32 Bits werden in% edx zurückgegeben. Die am wenigsten unsignierten langen langen signifikanten 32 Bits werden in% eax zurückgegeben.

Lasst uns versuchen, diese:

uint64_t some_function() { 
    return 18446744073709551614LLU; 
} 

Clang endet Herstellung:

pushl %ebp 
movl %esp, %ebp 
movl $-2, %eax 
movl $-1, %edx 
popl %ebp 
ret 

Interessanterweise asm_linux_amd64.s scheint das gleiche zu tun, uns einen Vorwand an der System V ABI for AMD64 zu sehen geben. Dieses Dokument erwähnt auch beiläufig RDX:

verwendet, um das 3. Argument zu Funktionen übergeben; 2. Rückkehr registrieren

Aber Anhang A befasst sich mit Linux-Konventionen speziell.

Die Schnittstelle zwischen der C-Bibliothek und der Linux-Kernel die gleichen wie für die mit den folgenden Unterschieden Anwendungen auf Benutzerebene ist:

von den Syscall Zurückgeben enthält Register% Rax das Ergebnis der Systemanruf. Ein Wert im Bereich zwischen -4095 und -1 zeigt einen Fehler an, ist es -errno.

Keine Erwähnung von RDX für den Systemaufruf.


Ich werde nicht meine Hand ins Feuer für diese setzen (oder allgemein), aber ich DX vermuten Einnahme ist nicht notwendig, für Linux, die nicht die Verwendung solcher großen Rückgabewerte macht, dass sie verschütten aus AXT.