diff options
Diffstat (limited to 'pkg/symbolizer/addr2line_test.go')
| -rw-r--r-- | pkg/symbolizer/addr2line_test.go | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/pkg/symbolizer/addr2line_test.go b/pkg/symbolizer/addr2line_test.go new file mode 100644 index 000000000..f6445367e --- /dev/null +++ b/pkg/symbolizer/addr2line_test.go @@ -0,0 +1,196 @@ +// Copyright 2016 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package symbolizer + +import ( + "bufio" + "fmt" + "os" + "reflect" + "strconv" + "testing" +) + +func TestParse(t *testing.T) { + addresses := []struct { + pc uint64 + resp string + frames []Frame + }{ + { + 0xffffffff8180a42e, + "0xffffffff8180a42e\n" + + "__asan_report_load2_noabort\n" + + "mm/kasan/report.c:320\n", + []Frame{ + { + PC: 0xffffffff8180a42e, + Func: "__asan_report_load2_noabort", + File: "mm/kasan/report.c", + Line: 320, + Inline: false, + }, + }, + }, + { + 0xffffffff8180a42d, + "0xffffffff8180a42d\n" + + "kasan_report\n" + + "mm/kasan/report.c:301\n" + + "__asan_report_load2_noabort\n" + + "mm/kasan/report.c:320\n", + []Frame{ + { + PC: 0xffffffff8180a42d, + Func: "kasan_report", + File: "mm/kasan/report.c", + Line: 301, + Inline: true, + }, + { + PC: 0xffffffff8180a42d, + Func: "__asan_report_load2_noabort", + File: "mm/kasan/report.c", + Line: 320, + Inline: false, + }, + }, + }, + { + 0xffffffff82fdbe0b, + "0xffffffff82fdbe0b\n" + + "fbcon_invert_region\n" + + "drivers/video/console/fbcon.c:2750\n", + []Frame{ + { + PC: 0xffffffff82fdbe0b, + Func: "fbcon_invert_region", + File: "drivers/video/console/fbcon.c", + Line: 2750, + Inline: false, + }, + }, + }, + { + 0x123124, + "0x0000000000123124\n" + + "??\n" + + "??:0\n", + nil, + }, + { + 0xffffffffffffffff, + "0xffffffffffffffff\n" + + "??\n" + + "??:0\n", + nil, + }, + { + 0xffffffff81a2aff9, + "0xffffffff81a2aff9\n" + + "devpts_get_priv\n" + + "fs/devpts/inode.c:588 (discriminator 3)\n", + []Frame{ + { + PC: 0xffffffff81a2aff9, + Func: "devpts_get_priv", + File: "fs/devpts/inode.c", + Line: 588, + Inline: false, + }, + }, + }, + } + + // Stub addr2line. + inputr, inputw, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + defer inputr.Close() + defer inputw.Close() + outputr, outputw, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + defer outputr.Close() + done := make(chan error) + go func() { + s := bufio.NewScanner(inputr) + loop: + for s.Scan() { + pc, err := strconv.ParseUint(s.Text(), 0, 64) + if err != nil { + outputw.Close() + done <- fmt.Errorf("got unexpected pc: %v", s.Text()) + return + } + for _, addr := range addresses { + if pc == addr.pc { + outputw.Write([]byte(addr.resp)) + continue loop + } + } + outputw.Close() + done <- fmt.Errorf("got unexpected pc: 0x%x", pc) + return + } + outputw.Write([]byte("DONE\n")) + outputw.Close() + close(done) + }() + defer func() { + inputw.Close() + if err := <-done; err != nil { + t.Fatal(err) + } + }() + + // First, symbolize all PCs one-by-one. + input := bufio.NewWriter(inputw) + scanner := bufio.NewScanner(outputr) + var interner Interner + var allPCs []uint64 + var allFrames []Frame + for _, addr := range addresses { + frames, err := symbolize(&interner, input, scanner, []uint64{addr.pc}) + if err != nil { + t.Fatalf("got error: %v", err) + } + if !reflect.DeepEqual(addr.frames, frames) { + t.Fatalf("want frames:\n%+v\ngot:\n%+v", addr.frames, frames) + } + allPCs = append(allPCs, addr.pc) + allFrames = append(allFrames, frames...) + } + + // Symbolize PCs in 2 groups. + for i := 0; i <= len(addresses); i++ { + frames, err := symbolize(&interner, input, scanner, allPCs[:i]) + if err != nil { + t.Fatalf("got error: %v", err) + } + frames2, err := symbolize(&interner, input, scanner, allPCs[i:]) + if err != nil { + t.Fatalf("got error: %v", err) + } + frames = append(frames, frames2...) + if !reflect.DeepEqual(allFrames, frames) { + t.Fatalf("want frames:\n%+v\ngot:\n%+v", allFrames, frames) + } + } + + // Symbolize a huge pile of PCs (test for pipe overflows). + lots := make([]uint64, 1e4) + for i := range lots { + lots[i] = addresses[0].pc + } + frames, err := symbolize(&interner, input, scanner, lots) + if err != nil { + t.Fatalf("got error: %v", err) + } + if want := len(lots) * len(addresses[0].frames); want != len(frames) { + t.Fatalf("want %v frames, got %v", want, len(frames)) + } +} |
