github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/symbolizer/addr2line_test.go (about) 1 // Copyright 2016 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package symbolizer 5 6 import ( 7 "bufio" 8 "fmt" 9 "os" 10 "reflect" 11 "strconv" 12 "testing" 13 ) 14 15 func TestParse(t *testing.T) { 16 addresses := []struct { 17 pc uint64 18 resp string 19 frames []Frame 20 }{ 21 { 22 0xffffffff8180a42e, 23 "0xffffffff8180a42e\n" + 24 "__asan_report_load2_noabort\n" + 25 "mm/kasan/report.c:320\n", 26 []Frame{ 27 { 28 PC: 0xffffffff8180a42e, 29 Func: "__asan_report_load2_noabort", 30 File: "mm/kasan/report.c", 31 Line: 320, 32 Inline: false, 33 }, 34 }, 35 }, 36 { 37 0xffffffff8180a42d, 38 "0xffffffff8180a42d\n" + 39 "kasan_report\n" + 40 "mm/kasan/report.c:301\n" + 41 "__asan_report_load2_noabort\n" + 42 "mm/kasan/report.c:320\n", 43 []Frame{ 44 { 45 PC: 0xffffffff8180a42d, 46 Func: "kasan_report", 47 File: "mm/kasan/report.c", 48 Line: 301, 49 Inline: true, 50 }, 51 { 52 PC: 0xffffffff8180a42d, 53 Func: "__asan_report_load2_noabort", 54 File: "mm/kasan/report.c", 55 Line: 320, 56 Inline: false, 57 }, 58 }, 59 }, 60 { 61 0xffffffff82fdbe0b, 62 "0xffffffff82fdbe0b\n" + 63 "fbcon_invert_region\n" + 64 "drivers/video/console/fbcon.c:2750\n", 65 []Frame{ 66 { 67 PC: 0xffffffff82fdbe0b, 68 Func: "fbcon_invert_region", 69 File: "drivers/video/console/fbcon.c", 70 Line: 2750, 71 Inline: false, 72 }, 73 }, 74 }, 75 { 76 0xffffffff82fdbe1b, 77 "0xffffffff82fdbe1b\n" + 78 "fbcon_invert_region\n" + 79 "drivers/video/console/fbcon.c:0\n", 80 []Frame{ 81 { 82 PC: 0xffffffff82fdbe1b, 83 Func: "fbcon_invert_region", 84 File: "drivers/video/console/fbcon.c", 85 Line: -1, 86 Inline: false, 87 }, 88 }, 89 }, 90 { 91 0x123124, 92 "0x0000000000123124\n" + 93 "??\n" + 94 "??:0\n", 95 nil, 96 }, 97 { 98 0xffffffffffffffff, 99 "0xffffffffffffffff\n" + 100 "??\n" + 101 "??:0\n", 102 nil, 103 }, 104 { 105 0xffffffff81a2aff9, 106 "0xffffffff81a2aff9\n" + 107 "devpts_get_priv\n" + 108 "fs/devpts/inode.c:588 (discriminator 3)\n", 109 []Frame{ 110 { 111 PC: 0xffffffff81a2aff9, 112 Func: "devpts_get_priv", 113 File: "fs/devpts/inode.c", 114 Line: 588, 115 Inline: false, 116 }, 117 }, 118 }, 119 } 120 121 // Stub addr2line. 122 inputr, inputw, err := os.Pipe() 123 if err != nil { 124 t.Fatal(err) 125 } 126 defer inputr.Close() 127 defer inputw.Close() 128 outputr, outputw, err := os.Pipe() 129 if err != nil { 130 t.Fatal(err) 131 } 132 defer outputr.Close() 133 done := make(chan error) 134 go func() { 135 s := bufio.NewScanner(inputr) 136 loop: 137 for s.Scan() { 138 pc, err := strconv.ParseUint(s.Text(), 0, 64) 139 if err != nil { 140 outputw.Close() 141 done <- fmt.Errorf("got unexpected pc: %v", s.Text()) 142 return 143 } 144 for _, addr := range addresses { 145 if pc == addr.pc { 146 outputw.Write([]byte(addr.resp)) 147 continue loop 148 } 149 } 150 outputw.Close() 151 done <- fmt.Errorf("got unexpected pc: 0x%x", pc) 152 return 153 } 154 outputw.Write([]byte("DONE\n")) 155 outputw.Close() 156 close(done) 157 }() 158 defer func() { 159 inputw.Close() 160 if err := <-done; err != nil { 161 t.Fatal(err) 162 } 163 }() 164 165 // First, symbolize all PCs one-by-one. 166 input := bufio.NewWriter(inputw) 167 scanner := bufio.NewScanner(outputr) 168 var interner Interner 169 var allPCs []uint64 170 var allFrames []Frame 171 for _, addr := range addresses { 172 frames, err := symbolize(&interner, input, scanner, []uint64{addr.pc}) 173 if err != nil { 174 t.Fatalf("got error: %v", err) 175 } 176 if !reflect.DeepEqual(addr.frames, frames) { 177 t.Fatalf("want frames:\n%+v\ngot:\n%+v", addr.frames, frames) 178 } 179 allPCs = append(allPCs, addr.pc) 180 allFrames = append(allFrames, frames...) 181 } 182 183 // Symbolize PCs in 2 groups. 184 for i := 0; i <= len(addresses); i++ { 185 frames, err := symbolize(&interner, input, scanner, allPCs[:i]) 186 if err != nil { 187 t.Fatalf("got error: %v", err) 188 } 189 frames2, err := symbolize(&interner, input, scanner, allPCs[i:]) 190 if err != nil { 191 t.Fatalf("got error: %v", err) 192 } 193 frames = append(frames, frames2...) 194 if !reflect.DeepEqual(allFrames, frames) { 195 t.Fatalf("want frames:\n%+v\ngot:\n%+v", allFrames, frames) 196 } 197 } 198 199 // Symbolize a huge pile of PCs (test for pipe overflows). 200 lots := make([]uint64, 1e4) 201 for i := range lots { 202 lots[i] = addresses[0].pc 203 } 204 frames, err := symbolize(&interner, input, scanner, lots) 205 if err != nil { 206 t.Fatalf("got error: %v", err) 207 } 208 if want := len(lots) * len(addresses[0].frames); want != len(frames) { 209 t.Fatalf("want %v frames, got %v", want, len(frames)) 210 } 211 }