diff --git a/src/runtime/print1.go b/src/runtime/print1.go index 3d812bd04422fa..7bec5599b5ddc8 100644 --- a/src/runtime/print1.go +++ b/src/runtime/print1.go @@ -75,7 +75,7 @@ func gwrite(b []byte) { } gp := getg() if gp == nil || gp.writebuf == nil { - write(2, unsafe.Pointer(&b[0]), int32(len(b))) + writeErr(b) return } diff --git a/src/runtime/print1_write.go b/src/runtime/print1_write.go new file mode 100644 index 00000000000000..5fd7d6519c42a9 --- /dev/null +++ b/src/runtime/print1_write.go @@ -0,0 +1,9 @@ +// +build !android + +package runtime + +import "unsafe" + +func writeErr(b []byte) { + write(2, unsafe.Pointer(&b[0]), int32(len(b))) +} diff --git a/src/runtime/print1_write_android.go b/src/runtime/print1_write_android.go new file mode 100644 index 00000000000000..d086e84b91b9b2 --- /dev/null +++ b/src/runtime/print1_write_android.go @@ -0,0 +1,44 @@ +package runtime + +import "unsafe" + +var ( + writeHeader = []byte{6 /* ANDROID_LOG_ERROR */, 'G', 'o', 0} + writePath = []byte("/dev/log/main\x00") + writeFD uintptr + writeBuf [1024]byte + writePos int +) + +func writeErr(b []byte) { + // Log format: "\x00\x00" + // The entire log needs to be delivered in a single syscall (the NDK + // does this with writev). Each log is its own line, so we need to + // buffer writes until we see a newline. + if writeFD == 0 { + writeFD = uintptr(open(&writePath[0], 0x1 /* O_WRONLY */, 0)) + if writeFD == 0 { + // It is hard to do anything here. Write to stderr just + // in case user has root on device and has run + // adb shell setprop log.redirect-stdio true + msg := []byte("runtime: cannot open /dev/log/main\x00") + write(2, unsafe.Pointer(&msg[0]), int32(len(msg))) + exit(2) + } + copy(writeBuf[:], writeHeader) + } + dst := writeBuf[len(writeHeader):] + for _, v := range b { + if v == 0 { // android logging won't print a zero byte + v = '0' + } + dst[writePos] = v + writePos++ + if v == '\n' || writePos == len(dst)-1 { + dst[writePos] = 0 + write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(len(writeHeader)+writePos)) + memclrBytes(dst) + writePos = 0 + } + } +}