--- /dev/null
+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: "<priority 1 byte><tag n bytes>\x00<message m bytes>\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
+ }
+ }
+}