1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
10 writeHeader
= []byte{6 /* ANDROID_LOG_ERROR */, 'G', 'o', 0}
11 writePath
= []byte("/dev/log/main\x00")
12 writeLogd
= []byte("/dev/socket/logdw\x00")
14 // guarded by printlock/printunlock.
20 // Prior to Android-L, logging was done through writes to /dev/log files implemented
21 // in kernel ring buffers. In Android-L, those /dev/log files are no longer
22 // accessible and logging is done through a centralized user-mode logger, logd.
24 // https://android.googlesource.com/platform/system/core/+/master/liblog/logd_write.c
28 unknown loggerType
= iota
31 // TODO(hakim): logging for emulator?
36 func writeErr(b
[]byte) {
37 if logger
== unknown
{
38 // Use logd if /dev/socket/logdw is available.
39 if v
:= uintptr(access(&writeLogd
[0], 0x02 /* W_OK */)); v
== 0 {
48 // Write to stderr for command-line programs.
49 write(2, unsafe
.Pointer(&b
[0]), int32(len(b
)))
51 // Log format: "<header>\x00<message m bytes>\x00"
54 // In legacy mode: "<priority 1 byte><tag n bytes>".
55 // In logd mode: "<android_log_header_t 11 bytes><priority 1 byte><tag n bytes>"
57 // The entire log needs to be delivered in a single syscall (the NDK
58 // does this with writev). Each log is its own line, so we need to
59 // buffer writes until we see a newline.
63 hlen
= writeLogdHeader()
65 hlen
= len(writeHeader
)
68 dst
:= writeBuf
[hlen
:]
70 if v
== 0 { // android logging won't print a zero byte
75 if v
== '\n' || writePos
== len(dst
)-1 {
77 write(writeFD
, unsafe
.Pointer(&writeBuf
[0]), int32(hlen
+writePos
))
85 // In legacy mode, logs are written to /dev/log/main
86 writeFD
= uintptr(open(&writePath
[0], 0x1 /* O_WRONLY */, 0))
88 // It is hard to do anything here. Write to stderr just
89 // in case user has root on device and has run
90 // adb shell setprop log.redirect-stdio true
91 msg
:= []byte("runtime: cannot open /dev/log/main\x00")
92 write(2, unsafe
.Pointer(&msg
[0]), int32(len(msg
)))
96 // Prepopulate the invariant header part.
97 copy(writeBuf
[:len(writeHeader
)], writeHeader
)
100 // used in initLogdWrite but defined here to avoid heap allocation.
101 var logdAddr sockaddr_un
104 // In logd mode, logs are sent to the logd via a unix domain socket.
105 logdAddr
.family
= _AF_UNIX
106 copy(logdAddr
.path
[:], writeLogd
)
108 // We are not using non-blocking I/O because writes taking this path
109 // are most likely triggered by panic, we cannot think of the advantage of
110 // non-blocking I/O for panic but see disadvantage (dropping panic message),
111 // and blocking I/O simplifies the code a lot.
112 fd
:= socket(_AF_UNIX
, _SOCK_DGRAM|_O_CLOEXEC
, 0)
114 msg
:= []byte("runtime: cannot create a socket for logging\x00")
115 write(2, unsafe
.Pointer(&msg
[0]), int32(len(msg
)))
119 errno
:= connect(fd
, unsafe
.Pointer(&logdAddr
), int32(unsafe
.Sizeof(logdAddr
)))
121 msg
:= []byte("runtime: cannot connect to /dev/socket/logdw\x00")
122 write(2, unsafe
.Pointer(&msg
[0]), int32(len(msg
)))
123 // TODO(hakim): or should we just close fd and hope for better luck next time?
126 writeFD
= uintptr(fd
)
128 // Prepopulate invariant part of the header.
129 // The first 11 bytes will be populated later in writeLogdHeader.
130 copy(writeBuf
[11:11+len(writeHeader
)], writeHeader
)
133 // writeLogdHeader populates the header and returns the length of the payload.
134 func writeLogdHeader() int {
137 // The first 11 bytes of the header corresponds to android_log_header_t
138 // as defined in system/core/include/private/android_logger.h
139 // hdr[0] log type id (unsigned char), defined in <log/log.h>
140 // hdr[1:2] tid (uint16_t)
141 // hdr[3:11] log_time defined in <log/log_read.h>
142 // hdr[3:7] sec unsigned uint32, little endian.
143 // hdr[7:11] nsec unsigned uint32, little endian.
144 hdr
[0] = 0 // LOG_ID_MAIN
145 sec
, nsec
:= time_now()
146 packUint32(hdr
[3:7], uint32(sec
))
147 packUint32(hdr
[7:11], uint32(nsec
))
149 // TODO(hakim): hdr[1:2] = gettid?
151 return 11 + len(writeHeader
)
154 func packUint32(b
[]byte, v
uint32) {