package runtime
import (
)
const debugLogBytes = 16 << 10
const debugLogStringLimit = debugLogBytes / 8
func () dlogger {
return dlog1()
}
func () dloggerFake {
return dloggerFake{}
}
func () *dloggerImpl {
, := uint64(cputicks()), uint64(nanotime())
:= getCachedDlogger()
if == nil {
:= (*uintptr)(unsafe.Pointer(&allDloggers))
:= (*dloggerImpl)(unsafe.Pointer(atomic.Loaduintptr()))
for := ; != nil; = .allLink {
if .owned.Load() == 0 && .owned.CompareAndSwap(0, 1) {
=
break
}
}
}
if == nil {
= (*dloggerImpl)(sysAllocOS(unsafe.Sizeof(dloggerImpl{})))
if == nil {
throw("failed to allocate debug log")
}
.w.r.data = &.w.data
.owned.Store(1)
:= (*uintptr)(unsafe.Pointer(&allDloggers))
for {
:= atomic.Loaduintptr()
.allLink = (*dloggerImpl)(unsafe.Pointer())
if atomic.Casuintptr(, , uintptr(unsafe.Pointer())) {
break
}
}
}
const = 1<<(3*7) - 1
if -.w.tick > || -.w.nano > {
.w.writeSync(, )
}
.w.ensure(debugLogHeaderSize)
.w.write += debugLogHeaderSize
.w.uvarint( - .w.tick)
.w.uvarint( - .w.nano)
:= getg()
if != nil && .m != nil && .m.p != 0 {
.w.varint(int64(.m.p.ptr().id))
} else {
.w.varint(-1)
}
return
}
type dloggerImpl struct {
_ sys.NotInHeap
w debugLogWriter
allLink *dloggerImpl
owned atomic.Uint32
}
var allDloggers *dloggerImpl
type dloggerFake struct{}
func ( dloggerFake) () {}
func ( *dloggerImpl) () {
:= .w.write - .w.r.end
if !.w.writeFrameAt(.w.r.end, ) {
throw("record too large")
}
.w.r.end = .w.write
if putCachedDlogger() {
return
}
.owned.Store(0)
}
const (
debugLogUnknown = 1 + iota
debugLogBoolTrue
debugLogBoolFalse
debugLogInt
debugLogUint
debugLogHex
debugLogPtr
debugLogString
debugLogConstString
debugLogStringOverflow
debugLogPC
debugLogTraceback
)
func ( dloggerFake) ( bool) dloggerFake { return }
func ( *dloggerImpl) ( bool) *dloggerImpl {
if {
.w.byte(debugLogBoolTrue)
} else {
.w.byte(debugLogBoolFalse)
}
return
}
func ( dloggerFake) ( int) dloggerFake { return }
func ( *dloggerImpl) ( int) *dloggerImpl {
return .i64(int64())
}
func ( dloggerFake) ( int8) dloggerFake { return }
func ( *dloggerImpl) ( int8) *dloggerImpl {
return .i64(int64())
}
func ( dloggerFake) ( int16) dloggerFake { return }
func ( *dloggerImpl) ( int16) *dloggerImpl {
return .i64(int64())
}
func ( dloggerFake) ( int32) dloggerFake { return }
func ( *dloggerImpl) ( int32) *dloggerImpl {
return .i64(int64())
}
func ( dloggerFake) ( int64) dloggerFake { return }
func ( *dloggerImpl) ( int64) *dloggerImpl {
.w.byte(debugLogInt)
.w.varint()
return
}
func ( dloggerFake) ( uint) dloggerFake { return }
func ( *dloggerImpl) ( uint) *dloggerImpl {
return .u64(uint64())
}
func ( dloggerFake) ( uintptr) dloggerFake { return }
func ( *dloggerImpl) ( uintptr) *dloggerImpl {
return .u64(uint64())
}
func ( dloggerFake) ( uint8) dloggerFake { return }
func ( *dloggerImpl) ( uint8) *dloggerImpl {
return .u64(uint64())
}
func ( dloggerFake) ( uint16) dloggerFake { return }
func ( *dloggerImpl) ( uint16) *dloggerImpl {
return .u64(uint64())
}
func ( dloggerFake) ( uint32) dloggerFake { return }
func ( *dloggerImpl) ( uint32) *dloggerImpl {
return .u64(uint64())
}
func ( dloggerFake) ( uint64) dloggerFake { return }
func ( *dloggerImpl) ( uint64) *dloggerImpl {
.w.byte(debugLogUint)
.w.uvarint()
return
}
func ( dloggerFake) ( uint64) dloggerFake { return }
func ( *dloggerImpl) ( uint64) *dloggerImpl {
.w.byte(debugLogHex)
.w.uvarint()
return
}
func ( dloggerFake) ( any) dloggerFake { return }
func ( *dloggerImpl) ( any) *dloggerImpl {
.w.byte(debugLogPtr)
if == nil {
.w.uvarint(0)
} else {
:= efaceOf(&)
switch ._type.Kind_ & abi.KindMask {
case abi.Chan, abi.Func, abi.Map, abi.Pointer, abi.UnsafePointer:
.w.uvarint(uint64(uintptr(.data)))
default:
throw("not a pointer type")
}
}
return
}
func ( dloggerFake) ( string) dloggerFake { return }
func ( *dloggerImpl) ( string) *dloggerImpl {
:= unsafe.StringData()
:= &firstmoduledata
if len() > 4 && .etext <= uintptr(unsafe.Pointer()) && uintptr(unsafe.Pointer()) < .end {
.w.byte(debugLogConstString)
.w.uvarint(uint64(len()))
.w.uvarint(uint64(uintptr(unsafe.Pointer()) - .etext))
} else {
.w.byte(debugLogString)
var []byte
:= (*slice)(unsafe.Pointer(&))
.array = unsafe.Pointer()
.len, .cap = len(), len()
if len() > debugLogStringLimit {
= [:debugLogStringLimit]
}
.w.uvarint(uint64(len()))
.w.bytes()
if len() != len() {
.w.byte(debugLogStringOverflow)
.w.uvarint(uint64(len() - len()))
}
}
return
}
func ( dloggerFake) ( uintptr) dloggerFake { return }
func ( *dloggerImpl) ( uintptr) *dloggerImpl {
.w.byte(debugLogPC)
.w.uvarint(uint64())
return
}
func ( dloggerFake) ( []uintptr) dloggerFake { return }
func ( *dloggerImpl) ( []uintptr) *dloggerImpl {
.w.byte(debugLogTraceback)
.w.uvarint(uint64(len()))
for , := range {
.w.uvarint(uint64())
}
return
}
type debugLogWriter struct {
_ sys.NotInHeap
write uint64
data debugLogBuf
tick, nano uint64
r debugLogReader
buf [10]byte
}
type debugLogBuf struct {
_ sys.NotInHeap
b [debugLogBytes]byte
}
const (
debugLogHeaderSize = 2
debugLogSyncSize = debugLogHeaderSize + 2*8
)
func ( *debugLogWriter) ( uint64) {
for .write+ >= .r.begin+uint64(len(.data.b)) {
if .r.skip() == ^uint64(0) {
throw("record wrapped around")
}
}
}
func ( *debugLogWriter) (, uint64) bool {
.data.b[%uint64(len(.data.b))] = uint8()
.data.b[(+1)%uint64(len(.data.b))] = uint8( >> 8)
return <= 0xFFFF
}
func ( *debugLogWriter) (, uint64) {
.tick, .nano = ,
.ensure(debugLogHeaderSize)
.writeFrameAt(.write, 0)
.write += debugLogHeaderSize
.writeUint64LE()
.writeUint64LE()
.r.end = .write
}
func ( *debugLogWriter) ( uint64) {
var [8]byte
[0] = byte()
[1] = byte( >> 8)
[2] = byte( >> 16)
[3] = byte( >> 24)
[4] = byte( >> 32)
[5] = byte( >> 40)
[6] = byte( >> 48)
[7] = byte( >> 56)
.bytes([:])
}
func ( *debugLogWriter) ( byte) {
.ensure(1)
:= .write
.write++
.data.b[%uint64(len(.data.b))] =
}
func ( *debugLogWriter) ( []byte) {
.ensure(uint64(len()))
:= .write
.write += uint64(len())
for len() > 0 {
:= copy(.data.b[%uint64(len(.data.b)):], )
+= uint64()
= [:]
}
}
func ( *debugLogWriter) ( int64) {
var uint64
if < 0 {
= (^uint64() << 1) | 1
} else {
= (uint64() << 1)
}
.uvarint()
}
func ( *debugLogWriter) ( uint64) {
:= 0
for >= 0x80 {
.buf[] = byte() | 0x80
>>= 7
++
}
.buf[] = byte()
++
.bytes(.buf[:])
}
type debugLogReader struct {
data *debugLogBuf
begin, end uint64
tick, nano uint64
}
func ( *debugLogReader) () uint64 {
if .begin+debugLogHeaderSize > .end {
return ^uint64(0)
}
:= uint64(.readUint16LEAt(.begin))
if == 0 {
.tick = .readUint64LEAt(.begin + debugLogHeaderSize)
.nano = .readUint64LEAt(.begin + debugLogHeaderSize + 8)
= debugLogSyncSize
}
if .begin+ > .end {
return ^uint64(0)
}
.begin +=
return
}
func ( *debugLogReader) ( uint64) uint16 {
return uint16(.data.b[%uint64(len(.data.b))]) |
uint16(.data.b[(+1)%uint64(len(.data.b))])<<8
}
func ( *debugLogReader) ( uint64) uint64 {
var [8]byte
for := range {
[] = .data.b[%uint64(len(.data.b))]
++
}
return uint64([0]) | uint64([1])<<8 |
uint64([2])<<16 | uint64([3])<<24 |
uint64([4])<<32 | uint64([5])<<40 |
uint64([6])<<48 | uint64([7])<<56
}
func ( *debugLogReader) () ( uint64) {
:= uint64(0)
for == 0 {
if .begin+debugLogHeaderSize > .end {
return ^uint64(0)
}
= uint64(.readUint16LEAt(.begin))
if != 0 {
break
}
if .begin+debugLogSyncSize > .end {
return ^uint64(0)
}
.tick = .readUint64LEAt(.begin + debugLogHeaderSize)
.nano = .readUint64LEAt(.begin + debugLogHeaderSize + 8)
.begin += debugLogSyncSize
}
if .begin+ > .end {
return ^uint64(0)
}
:= .begin + debugLogHeaderSize
var uint64
for := uint(0); ; += 7 {
:= .data.b[%uint64(len(.data.b))]
++
|= uint64(&^0x80) <<
if &0x80 == 0 {
break
}
}
if > .begin+ {
return ^uint64(0)
}
return .tick +
}
func ( *debugLogReader) () (, , uint64, int) {
:= uint64(.readUint16LEAt(.begin))
= .begin +
.begin += debugLogHeaderSize
= .uvarint() + .tick
= .uvarint() + .nano
= int(.varint())
return
}
func ( *debugLogReader) () uint64 {
var uint64
for := uint(0); ; += 7 {
:= .data.b[.begin%uint64(len(.data.b))]
.begin++
|= uint64(&^0x80) <<
if &0x80 == 0 {
break
}
}
return
}
func ( *debugLogReader) () int64 {
:= .uvarint()
var int64
if &1 == 0 {
= int64( >> 1)
} else {
= ^int64( >> 1)
}
return
}
func ( *debugLogReader) () bool {
:= .data.b[.begin%uint64(len(.data.b))]
.begin++
switch {
default:
print("<unknown field type ", hex(), " pos ", .begin-1, " end ", .end, ">\n")
return false
case debugLogUnknown:
print("<unknown kind>")
case debugLogBoolTrue:
print(true)
case debugLogBoolFalse:
print(false)
case debugLogInt:
print(.varint())
case debugLogUint:
print(.uvarint())
case debugLogHex, debugLogPtr:
print(hex(.uvarint()))
case debugLogString:
:= .uvarint()
if .begin+ > .end {
.begin = .end
print("<string length corrupted>")
break
}
for > 0 {
:= .data.b[.begin%uint64(len(.data.b)):]
if uint64(len()) > {
= [:]
}
.begin += uint64(len())
-= uint64(len())
gwrite()
}
case debugLogConstString:
, := int(.uvarint()), uintptr(.uvarint())
+= firstmoduledata.etext
:= stringStruct{
str: unsafe.Pointer(),
len: ,
}
:= *(*string)(unsafe.Pointer(&))
print()
case debugLogStringOverflow:
print("..(", .uvarint(), " more bytes)..")
case debugLogPC:
printDebugLogPC(uintptr(.uvarint()), false)
case debugLogTraceback:
:= int(.uvarint())
for := 0; < ; ++ {
print("\n\t")
printDebugLogPC(uintptr(.uvarint()), true)
}
}
return true
}
func () {
if dlogEnabled {
printDebugLogImpl()
}
}
func () {
printlock()
:= (*uintptr)(unsafe.Pointer(&allDloggers))
:= (*dloggerImpl)(unsafe.Pointer(atomic.Loaduintptr()))
:= 0
for := ; != nil; = .allLink {
++
}
if == 0 {
printunlock()
return
}
type struct {
debugLogReader
bool
uint64
uint64
}
:= sysAllocOS(unsafe.Sizeof({}) * uintptr())
if == nil {
println("failed to allocate read state for", , "logs")
printunlock()
return
}
:= (*[1 << 20])()[:]
{
:=
for := range {
:= &[]
. = .w.r
. = true
. = .w.r.begin
. = .peek()
= .allLink
}
}
for {
var struct {
uint64
int
}
. = ^uint64(0)
for := range {
if []. < . {
. = [].
. =
}
}
if . == ^uint64(0) {
break
}
:= &[.]
if . {
print(">> begin log ", .)
if . != 0 {
print("; lost first ", .>>10, "KB")
}
print(" <<\n")
. = false
}
, , , := .header()
:= .end
.end =
print("[")
var [21]byte
:= int64() - runtimeInitTime
if < 0 {
= 0
}
:= itoaDiv([:], uint64(), 9)
print(slicebytetostringtmp((*byte)(noescape(unsafe.Pointer(&[0]))), len()))
print(" P ", , "] ")
for := 0; .begin < .end; ++ {
if > 0 {
print(" ")
}
if !.printVal() {
print("<aborting P log>")
=
break
}
}
println()
.begin =
.end =
. = .peek()
}
printunlock()
}
func ( uintptr, bool) {
:= findfunc()
if && (!.valid() || > .entry()) {
--
}
print(hex())
if !.valid() {
print(" [unknown PC]")
} else {
:= funcname()
, := funcline(, )
print(" [", , "+", hex(-.entry()),
" ", , ":", , "]")
}
}