1// skip
2
3// Copyright 2015 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// This is built by issue10607.go with a -B option.
8// Verify that we have one build-id note with the expected value.
9
10package main
11
12import (
13	"bytes"
14	"debug/elf"
15	"fmt"
16	"os"
17)
18
19func main() {
20	f, err := elf.Open("/proc/self/exe")
21	if err != nil {
22		if os.IsNotExist(err) {
23			return
24		}
25		fmt.Fprintln(os.Stderr, "opening /proc/self/exe:", err)
26		os.Exit(1)
27	}
28
29	c := 0
30	fail := false
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			fmt.Fprintf(os.Stderr, "reading data of note section %d: %v\n", i, err)
39			continue
40		}
41
42		for len(d) > 0 {
43			namesz := f.ByteOrder.Uint32(d)
44			descsz := f.ByteOrder.Uint32(d[4:])
45			typ := f.ByteOrder.Uint32(d[8:])
46
47			an := (namesz + 3) &^ 3
48			ad := (descsz + 3) &^ 3
49
50			if int(12+an+ad) > len(d) {
51				fmt.Fprintf(os.Stderr, "note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))\n", i, len(d), namesz, descsz)
52				break
53			}
54
55			// 3 == NT_GNU_BUILD_ID
56			if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) {
57				id := string(d[12+an:12+an+descsz])
58				if id == "\x12\x34\x56\x78" {
59					c++
60				} else {
61					fmt.Fprintf(os.Stderr, "wrong build ID data: %q\n", id)
62					fail = true
63				}
64			}
65
66			d = d[12+an+ad:]
67		}
68	}
69
70	if c == 0 {
71		fmt.Fprintln(os.Stderr, "no build-id note")
72		fail = true
73	} else if c > 1 {
74		fmt.Fprintln(os.Stderr, c, "build-id notes")
75		fail = true
76	}
77
78	if fail {
79		os.Exit(1)
80	}
81}
82