1// Copyright 2022 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package pe
6
7import (
8	"fmt"
9	"testing"
10)
11
12type testpoint struct {
13	name   string
14	ok     bool
15	err    string
16	auxstr string
17}
18
19func TestReadCOFFSymbolAuxInfo(t *testing.T) {
20	testpoints := map[int]testpoint{
21		39: testpoint{
22			name:   ".rdata$.refptr.__native_startup_lock",
23			ok:     true,
24			auxstr: "{Size:8 NumRelocs:1 NumLineNumbers:0 Checksum:0 SecNum:16 Selection:2 _:[0 0 0]}",
25		},
26		81: testpoint{
27			name:   ".debug_line",
28			ok:     true,
29			auxstr: "{Size:994 NumRelocs:1 NumLineNumbers:0 Checksum:1624223678 SecNum:32 Selection:0 _:[0 0 0]}",
30		},
31		155: testpoint{
32			name: ".file",
33			ok:   false,
34			err:  "incorrect symbol storage class",
35		},
36	}
37
38	// The testdata PE object file below was selected from a release
39	// build from https://github.com/mstorsjo/llvm-mingw/releases; it
40	// corresponds to the mingw "crt2.o" object. The object itself was
41	// built using an x86_64 HOST=linux TARGET=windows clang cross
42	// compiler based on LLVM 13. More build details can be found at
43	// https://github.com/mstorsjo/llvm-mingw/releases.
44	f, err := Open("testdata/llvm-mingw-20211002-msvcrt-x86_64-crt2")
45	if err != nil {
46		t.Errorf("open failed with %v", err)
47	}
48	defer f.Close()
49	for k := range f.COFFSymbols {
50		tp, ok := testpoints[k]
51		if !ok {
52			continue
53		}
54		sym := &f.COFFSymbols[k]
55		if sym.NumberOfAuxSymbols == 0 {
56			t.Errorf("expected aux symbols for sym %d", k)
57			continue
58		}
59		name, nerr := sym.FullName(f.StringTable)
60		if nerr != nil {
61			t.Errorf("FullName(%d) failed with %v", k, nerr)
62			continue
63		}
64		if name != tp.name {
65			t.Errorf("name check for %d, got %s want %s", k, name, tp.name)
66			continue
67		}
68		ap, err := f.COFFSymbolReadSectionDefAux(k)
69		if tp.ok {
70			if err != nil {
71				t.Errorf("unexpected failure on %d, got error %v", k, err)
72				continue
73			}
74			got := fmt.Sprintf("%+v", *ap)
75			if got != tp.auxstr {
76				t.Errorf("COFFSymbolReadSectionDefAux on %d bad return, got:\n%s\nwant:\n%s\n", k, got, tp.auxstr)
77				continue
78			}
79		} else {
80			if err == nil {
81				t.Errorf("unexpected non-failure on %d", k)
82				continue
83			}
84			got := fmt.Sprintf("%v", err)
85			if got != tp.err {
86				t.Errorf("COFFSymbolReadSectionDefAux %d wrong error, got %q want %q", k, got, tp.err)
87				continue
88			}
89		}
90	}
91}
92