GetBuildID returns the GNU build-ID for an ELF binary. If no build-ID was found but the binary was read without error, it returns (nil, nil).
(f *elf.File)
| 119 | // If no build-ID was found but the binary was read without error, it returns |
| 120 | // (nil, nil). |
| 121 | func GetBuildID(f *elf.File) ([]byte, error) { |
| 122 | findBuildID := func(notes []elfNote) ([]byte, error) { |
| 123 | var buildID []byte |
| 124 | for _, note := range notes { |
| 125 | if note.Name == "GNU" && note.Type == noteTypeGNUBuildID { |
| 126 | if buildID == nil { |
| 127 | buildID = note.Desc |
| 128 | } else { |
| 129 | return nil, fmt.Errorf("multiple build ids found, don't know which to use") |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | return buildID, nil |
| 134 | } |
| 135 | |
| 136 | for _, p := range f.Progs { |
| 137 | if p.Type != elf.PT_NOTE { |
| 138 | continue |
| 139 | } |
| 140 | notes, err := parseNotes(p.Open(), int(p.Align), f.ByteOrder) |
| 141 | if err != nil { |
| 142 | return nil, err |
| 143 | } |
| 144 | if b, err := findBuildID(notes); b != nil || err != nil { |
| 145 | return b, err |
| 146 | } |
| 147 | } |
| 148 | for _, s := range f.Sections { |
| 149 | if s.Type != elf.SHT_NOTE { |
| 150 | continue |
| 151 | } |
| 152 | notes, err := parseNotes(s.Open(), int(s.Addralign), f.ByteOrder) |
| 153 | if err != nil { |
| 154 | return nil, err |
| 155 | } |
| 156 | if b, err := findBuildID(notes); b != nil || err != nil { |
| 157 | return b, err |
| 158 | } |
| 159 | } |
| 160 | return nil, nil |
| 161 | } |
| 162 | |
| 163 | // kernelBase calculates the base for kernel mappings, which usually require |
| 164 | // special handling. For kernel mappings, tools (like perf) use the address of |
no test coverage detected
searching dependent graphs…