Source file src/cmd/cgo/internal/test/buildid_linux.go

     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  sections:
    31  	for i, s := range f.Sections {
    32  		if s.Type != elf.SHT_NOTE {
    33  			continue
    34  		}
    35  
    36  		d, err := s.Data()
    37  		if err != nil {
    38  			t.Logf("reading data of note section %d: %v", i, err)
    39  			continue
    40  		}
    41  
    42  		for len(d) > 0 {
    43  
    44  			// ELF standards differ as to the sizes in
    45  			// note sections.  Both the GNU linker and
    46  			// gold always generate 32-bit sizes, so that
    47  			// is what we assume here.
    48  
    49  			if len(d) < 12 {
    50  				t.Logf("note section %d too short (%d < 12)", i, len(d))
    51  				continue sections
    52  			}
    53  
    54  			namesz := f.ByteOrder.Uint32(d)
    55  			descsz := f.ByteOrder.Uint32(d[4:])
    56  			typ := f.ByteOrder.Uint32(d[8:])
    57  
    58  			an := (namesz + 3) &^ 3
    59  			ad := (descsz + 3) &^ 3
    60  
    61  			if int(12+an+ad) > len(d) {
    62  				t.Logf("note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))", i, len(d), namesz, descsz)
    63  				continue sections
    64  			}
    65  
    66  			// 3 == NT_GNU_BUILD_ID
    67  			if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) {
    68  				c++
    69  			}
    70  
    71  			d = d[12+an+ad:]
    72  		}
    73  	}
    74  
    75  	if c > 1 {
    76  		t.Errorf("found %d build ID notes", c)
    77  	}
    78  }
    79  

View as plain text