blob: a3a86edfca883dc651bd2ec16efeb2f27159ca8f [file] [log] [blame]
Ian Lance Taylor7fdb0292014-08-07 12:38:39 -07001// Copyright 2014 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 cgotest
6
7// Test that we have no more than one build ID. In the past we used
8// to generate a separate build ID for each package using cgo, and the
9// linker concatenated them all. We don't want that--we only want
10// one.
11
12import (
13 "bytes"
14 "debug/elf"
15 "os"
16 "testing"
17)
18
19func testBuildID(t *testing.T) {
20 f, err := elf.Open("/proc/self/exe")
21 if err != nil {
22 if os.IsNotExist(err) {
23 t.Skip("no /proc/self/exe")
24 }
25 t.Fatalf("opening /proc/self/exe: ", err)
26 }
27 defer f.Close()
28
29 c := 0
30 for i, s := range f.Sections {
31 if s.Type != elf.SHT_NOTE {
32 continue
33 }
34
35 d, err := s.Data()
36 if err != nil {
37 t.Logf("reading data of note section %d: %v", i, err)
38 continue
39 }
40
41 for len(d) > 0 {
42
43 // ELF standards differ as to the sizes in
44 // note sections. Both the GNU linker and
45 // gold always generate 32-bit sizes, so that
46 // is what we assume here.
47
48 if len(d) < 12 {
49 t.Logf("note section %d too short (%d < 12)", i, len(d))
50 continue
51 }
52
53 namesz := f.ByteOrder.Uint32(d)
54 descsz := f.ByteOrder.Uint32(d[4:])
55 typ := f.ByteOrder.Uint32(d[8:])
56
57 an := (namesz + 3) &^ 3
58 ad := (descsz + 3) &^ 3
59
60 if int(12+an+ad) > len(d) {
61 t.Logf("note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))", i, len(d), namesz, descsz)
62 continue
63 }
64
65 // 3 == NT_GNU_BUILD_ID
66 if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) {
67 c++
68 }
69
70 d = d[12+an+ad:]
71 }
72 }
73
74 if c > 1 {
75 t.Errorf("found %d build ID notes", c)
76 }
77}