github.com/ks888/tgo@v0.0.0-20190130135156-80bf89407292/tracee/binary_linux.go (about)

     1  package tracee
     2  
     3  import (
     4  	"bytes"
     5  	"compress/zlib"
     6  	"debug/dwarf"
     7  	"debug/elf"
     8  	"encoding/binary"
     9  	"io"
    10  )
    11  
    12  var locationListSectionNames = []string{
    13  	".zdebug_loc",
    14  	".debug_loc",
    15  }
    16  
    17  func openBinaryFile(pathToProgram string, goVersion GoVersion) (BinaryFile, error) {
    18  	elfFile, err := elf.Open(pathToProgram)
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  	var closer io.Closer = elfFile
    23  
    24  	data, locList, err := findDWARF(elfFile)
    25  	if err != nil {
    26  		binaryFile, err := newNonDebuggableBinaryFile(closer)
    27  		if err != nil {
    28  			closer.Close()
    29  		}
    30  		return binaryFile, err
    31  	}
    32  
    33  	binaryFile, err := newDebuggableBinaryFile(dwarfData{Data: data, locationList: locList}, goVersion, closer)
    34  	if err != nil {
    35  		closer.Close()
    36  	}
    37  	return binaryFile, err
    38  }
    39  
    40  func findDWARF(elfFile *elf.File) (data *dwarf.Data, locList []byte, err error) {
    41  	var locListSection *elf.Section
    42  	for _, locListSectionName := range locationListSectionNames {
    43  		locListSection = elfFile.Section(locListSectionName)
    44  		if locListSection != nil {
    45  			break
    46  		}
    47  	}
    48  	// older go version doesn't create a location list section.
    49  
    50  	locList, err = buildLocationListData(locListSection)
    51  	if err != nil {
    52  		return nil, nil, err
    53  	}
    54  
    55  	data, err = elfFile.DWARF()
    56  	return data, locList, err
    57  }
    58  
    59  func buildLocationListData(locListSection *elf.Section) ([]byte, error) {
    60  	if locListSection == nil {
    61  		return nil, nil
    62  	}
    63  
    64  	rawData, err := locListSection.Data()
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	if string(rawData[:4]) != "ZLIB" || len(rawData) < 12 {
    70  		return rawData, nil
    71  	}
    72  
    73  	dlen := binary.BigEndian.Uint64(rawData[4:12])
    74  	uncompressedData := make([]byte, dlen)
    75  
    76  	r, err := zlib.NewReader(bytes.NewBuffer(rawData[12:]))
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	defer r.Close()
    81  
    82  	_, err = io.ReadFull(r, uncompressedData)
    83  	return uncompressedData, err
    84  }