77package core
88
99import (
10+ "encoding/binary"
1011 "os"
12+ "syscall"
1113 _ "unsafe" // for go:linkname
1214)
1315
16+ var pid int
17+
1418func init () {
1519 // github.com/golang/go/issues/69868
1620 // Unfortunately, Android apps have AT_SECURE set
@@ -30,6 +34,8 @@ func init() {
3034 // Change level to assert in the hope that Android's DropBoxManager picks it up.
3135 // github.com/golang/go/issues/25035 / developer.android.com/reference/kotlin/android/util/Log#ASSERT:kotlin.Int
3236 writeHeader = []byte {7 /* ANDROID_LOG_ASSERT */ , 'G' , 'o' , 'E' , 'r' , 'r' , 0 }
37+
38+ pid = syscall .Getpid ()
3339}
3440
3541func SecureMode (new bool ) (prev bool ) {
@@ -92,6 +98,8 @@ func GetRuntimeEnviron(key string) (val string, found bool) {
9298 return
9399}
94100
101+ // RuntimeWtf uses runtime.writeHeader and emits s to logd.
102+ // github.com/golang/go/blob/e2fef50def98/src/runtime/write_err_android.go#L39
95103func RuntimeWtf (s string ) {
96104 runtime_wtf ([]byte (s ))
97105}
@@ -111,7 +119,39 @@ func runtime_gotraceback() (int32, bool, bool)
111119//go:linkname runtime_wtf runtime.writeErr
112120func runtime_wtf (b []byte )
113121
114- // pushing func symbols does not work on go1.24+
122+ //go:linkname runtime_timenow runtime.time_now
123+ func runtime_timenow () (sec int64 , nsec int32 , mono int64 )
124+
125+ // pushing func symbols does not work on go1.24+?
126+
127+ // writeLogdHeader prints crash logs to main buffer; the change here
128+ // redirects it to crash buffer instead, which among other things, is
129+ // retained for longer & gets picked up by Android Vitals (via DropBoxManager).
130+ // github.com/golang/go/blob/e2fef50def98/src/runtime/write_err_android.go#L19
131+
132+ //go:linkname runtime.writeLogdHeader
133+ func writeLogdHeader () int {
134+ hdr := writeBuf [:11 ]
135+
136+ // The first 11 bytes of the header corresponds to android_log_header_t
137+ // as defined in system/core/include/private/android_logger.h
138+ // hdr[0] log type id (unsigned char), defined in <log/log.h>
139+ // hdr[1:2] tid (uint16_t)
140+ // hdr[3:11] log_time defined in <log/log_read.h>
141+ // hdr[3:7] sec unsigned uint32, little endian.
142+ // hdr[7:11] nsec unsigned uint32, little endian.
143+ // cs.android.com/android/platform/superproject/main/+/main:system/logging/liblog/include/android/log.h;drc=90ddfb0bd41fbb41d045f04e02476ddce200d535;l=163
144+ hdr [0 ] = 4 // LOG_ID_CRASH
145+ sec , nsec , _ := runtime_timenow ()
146+ binary .LittleEndian .PutUint32 (hdr [3 :7 ], uint32 (sec ))
147+ binary .LittleEndian .PutUint32 (hdr [7 :11 ], uint32 (nsec ))
148+ // gettid is not signal safe; use pid (mainthread) instead
149+ // man7.org/linux/man-pages/man7/signal-safety.7.html
150+ binary .LittleEndian .PutUint16 (hdr [1 :2 ], uint16 (pid ))
151+
152+ return 11 + len (writeHeader )
153+ }
154+
115155// but pushing vars apparently still works provided
116156// -ldflags="checklinkname=0"
117157
@@ -120,3 +160,6 @@ var secureMode bool
120160
121161//go:linkname writeHeader runtime.writeHeader
122162var writeHeader []byte
163+
164+ //go:linkname writeBuf runtime.writeBuf
165+ var writeBuf [1024 ]byte
0 commit comments