// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pprof

import (
	
	
	
	
)

var (
	errBadELF    = errors.New("malformed ELF binary")
	errNoBuildID = errors.New("no NT_GNU_BUILD_ID found in ELF binary")
)

// elfBuildID returns the GNU build ID of the named ELF binary,
// without introducing a dependency on debug/elf and its dependencies.
func elfBuildID( string) (string, error) {
	 := make([]byte, 256)
	,  := os.Open()
	if  != nil {
		return "", 
	}
	defer .Close()

	if ,  := .ReadAt([:64], 0);  != nil {
		return "", 
	}

	// ELF file begins with \x7F E L F.
	if [0] != 0x7F || [1] != 'E' || [2] != 'L' || [3] != 'F' {
		return "", errBadELF
	}

	var  binary.ByteOrder
	switch [5] {
	default:
		return "", errBadELF
	case 1: // little-endian
		 = binary.LittleEndian
	case 2: // big-endian
		 = binary.BigEndian
	}

	var  int
	var ,  int64
	switch [4] {
	default:
		return "", errBadELF
	case 1: // 32-bit file header
		 = int64(.Uint32([32:]))
		 = int64(.Uint16([46:]))
		if  != 40 {
			return "", errBadELF
		}
		 = int(.Uint16([48:]))
	case 2: // 64-bit file header
		 = int64(.Uint64([40:]))
		 = int64(.Uint16([58:]))
		if  != 64 {
			return "", errBadELF
		}
		 = int(.Uint16([60:]))
	}

	for  := 0;  < ; ++ {
		if ,  := .ReadAt([:], +int64()*);  != nil {
			return "", 
		}
		if  := .Uint32([4:]);  != 7 { // SHT_NOTE
			continue
		}
		var ,  int64
		if  == 40 {
			// 32-bit section header
			 = int64(.Uint32([16:]))
			 = int64(.Uint32([20:]))
		} else {
			// 64-bit section header
			 = int64(.Uint64([24:]))
			 = int64(.Uint64([32:]))
		}
		 += 
		for  <  {
			if ,  := .ReadAt([:16], );  != nil { // room for header + name GNU\x00
				return "", 
			}
			 := int(.Uint32([0:]))
			 := int(.Uint32([4:]))
			 := int(.Uint32([8:]))
			 :=  + int64(12+(+3)&^3)
			 =  + int64((+3)&^3)
			if  != 4 ||  != 3 || [12] != 'G' || [13] != 'N' || [14] != 'U' || [15] != '\x00' { // want name GNU\x00 type 3 (NT_GNU_BUILD_ID)
				continue
			}
			if  > len() {
				return "", errBadELF
			}
			if ,  := .ReadAt([:], );  != nil {
				return "", 
			}
			return fmt.Sprintf("%x", [:]), nil
		}
	}
	return "", errNoBuildID
}