aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/symbolizer/addr2line_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/symbolizer/addr2line_test.go')
-rw-r--r--pkg/symbolizer/addr2line_test.go196
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))
+ }
+}