Skip to content

Commit 8717d92

Browse files
committed
core/overreach: redirect runtime err to crash buffer
1 parent 4d0e46a commit 8717d92

1 file changed

Lines changed: 44 additions & 1 deletion

File tree

intra/core/overreach.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
package core
88

99
import (
10+
"encoding/binary"
1011
"os"
12+
"syscall"
1113
_ "unsafe" // for go:linkname
1214
)
1315

16+
var pid int
17+
1418
func 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

3541
func 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
95103
func 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
112120
func 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
122162
var writeHeader []byte
163+
164+
//go:linkname writeBuf runtime.writeBuf
165+
var writeBuf [1024]byte

0 commit comments

Comments
 (0)