github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/misc/cgo/test/buildid_linux.go (about) 1 // 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 5 package 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 12 import ( 13 "bytes" 14 "debug/elf" 15 "os" 16 "testing" 17 ) 18 19 func 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.Fatal("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 }