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  }