About me:
This talk will only refer to the main Go implementation
(the one in github.com/golang/go).
Several other implementations of Go exist.
Go - typical programming languages facts
↓ C code ↓ | ||||||
Compiler (GCC) | ||||||
↓ human-readable assembly ↓ | ||||||
Assembler (binutils) | ||||||
↓ machine-readable assembly ↓ | ||||||
Linker (binutils) | ||||||
executable | → | glue code (ld.so) | → | libc | → | kernel |
↓ Go code ↓ | ||||
Compiler | ||||
↓ human-readable assembly ↓ | ||||
Assembler | ||||
↓ machine-readable assembly ↓ | ||||
Linker | ||||
executable | → | libc | → | kernel |
Why not libc?
Overhead:
~/g/src> env GOOS=netbsd GOARCH=arm64 bash ./make.bash ... Building packages and commands for target, netbsd/arm64. cmd/go: unsupported GOOS/GOARCH pair netbsd/arm64
Error strings come from somewhere.
lwp_create, lwp_tramp, osyield, lwp_park, lwp_unpark, lwp_self, exit, exitThread, open, closefd, read, write, usleep, raise, raiseproc, setitimer, walltime, nanotime, getcontext, sigprocmask, sigreturn_tramp, sigaction, sigfwd, sigtramp, mmap, munmap, madvise, sigaltstack, settls, sysctl, kqueue, kevent, closeonexec.
/usr/include/sys/syscall.h
/* syscall: "exit" ret: "void" args: "int" */ #define SYS_exit 1
Register | Special | Role |
SP | Stack pointer | |
r30 | LR | Link register |
r29 | FP | Frame pointer |
r19..r28 | Callee-saved registers | |
r9..r15 | Temporary registers | |
r8 | Indirect result location register | |
r0..r7 | Parameter/result registers |
objdump -d /lib/libc.so
_exit: 191810: 21 00 00 d4 svc #0x1 191814: c0 03 5f d6 ret
auto-generate, easier with SYS_syscall
func Sync() (err error) { _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) if e1 != 0 { err = errnoErr(e1) } return }
// func RawSyscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr) TEXT ·RawSyscall(SB),NOSPLIT,$0-56 MOVD trap+0(FP), R17 // syscall entry MOVD a1+8(FP), R0 MOVD a2+16(FP), R1 MOVD a3+24(FP), R2 SVC $SYS_syscall BCC ok MOVD $-1, R1 MOVD R1, r1+32(FP) // r1 MOVD ZR, r2+40(FP) // r2 MOVD R0, err+48(FP) // err RET ok: MOVD R0, r1+32(FP) // r1 MOVD R1, r2+40(FP) // r2 MOVD ZR, err+48(FP) // err RET
> ktruss -i ./hello ... 34 1 hello __sigprocmask14(0x3, 0, 0x1840c0) = 0 34 1 hello __clock_gettime50(0x3, 0xffffffffe8b8) = 0