Colorize renders a callstack as a multi-line, ANSI-colourised string. It works directly with the typed Frame slice so no string parsing is required. Visual hierarchy per frame (left > right, dim > bright): ! Frame tiers ──────
()
| 45 | // Consecutive unresolved frames (kernel-space with no symbol) are collapsed |
| 46 | // into a single dim counter line to avoid flooding the view. |
| 47 | func (s Callstack) Colorize() string { |
| 48 | if s.IsEmpty() { |
| 49 | return "" |
| 50 | } |
| 51 | |
| 52 | // iterate in reverse so the outermost frame comes first |
| 53 | depth := s.Depth() |
| 54 | l := s.maxAddrLength() |
| 55 | |
| 56 | var idx int |
| 57 | var unresolved int |
| 58 | var b strings.Builder |
| 59 | b.Grow(depth * 100) |
| 60 | |
| 61 | flushUnresolved := func() { |
| 62 | if unresolved == 0 { |
| 63 | return |
| 64 | } |
| 65 | line := fmt.Sprintf(" %s %d unresolved %s", |
| 66 | colorizer.SpanDim("▸"), |
| 67 | unresolved, |
| 68 | "frame(s)", |
| 69 | ) |
| 70 | b.WriteString(colorizer.SpanDim(colorizer.Span(colorizer.Gray, line))) |
| 71 | b.WriteByte('\n') |
| 72 | unresolved = 0 |
| 73 | } |
| 74 | |
| 75 | for i := depth - 1; i >= 0; i-- { |
| 76 | f := s.FrameAt(i) |
| 77 | |
| 78 | // frames in kernel range with no resolved symbol are unresolved so |
| 79 | // we can collapse them into a counter |
| 80 | if f.Addr.InSystemRange() && (f.Symbol == "" || f.Symbol == "?") { |
| 81 | unresolved++ |
| 82 | continue |
| 83 | } |
| 84 | |
| 85 | flushUnresolved() |
| 86 | idx++ |
| 87 | |
| 88 | // draw gutter |
| 89 | b.WriteString(colorizer.SpanDim(colorizer.Span(colorizer.Gray, fmt.Sprintf(" %3d ", idx)))) |
| 90 | |
| 91 | // draw address |
| 92 | addrStr := "0x" + f.Addr.String() |
| 93 | paddedAddr := addrStr + strings.Repeat(" ", l-len(addrStr)) |
| 94 | b.WriteString(colorizer.SpanDim(colorizer.Span(colorizer.Gray, paddedAddr))) |
| 95 | b.WriteString(" ") |
| 96 | |
| 97 | // unbacked means execution from anonymous memory which is the highest- |
| 98 | // suspicion tier, rendered red regardless of address range. |
| 99 | if f.IsUnbacked() { |
| 100 | b.WriteString(f.colorizeUnbacked()) |
| 101 | b.WriteByte('\n') |
| 102 | continue |
| 103 | } |
| 104 |
nothing calls this directly
no test coverage detected