func()

in pkg/tools/btf/linker.go [286:348]


func (u *UProbeExeFile) addGoExitLink0(symbol string, p *ebpf.Program, elfFile *elf.File) ([]link.Link, error) {
	// find the symbol
	targetSymbol := elfFile.FindSymbol(symbol)
	if targetSymbol == nil {
		return nil, fmt.Errorf("could not found the symbol")
	}

	// find the symbol real data buffer
	buffer, err := elfFile.ReadSymbolData(".text", targetSymbol.Location, targetSymbol.Size)
	if err != nil {
		return nil, fmt.Errorf("reading symbol data error: %v", err)
	}

	// based on the base addresses and symbol data buffer
	// calculate all RET addresses
	// https://github.com/iovisor/bcc/issues/1320#issuecomment-407927542
	var addresses []uint64
	for i := 0; i < int(targetSymbol.Size); {
		var instLen int
		if runtime.GOARCH == "arm64" {
			inst, err := arm64asm.Decode(buffer[i:])
			if err != nil {
				i += 4
				continue
			}

			if inst.Op == arm64asm.RET {
				addresses = append(addresses, uint64(i))
			}

			instLen = 4
		} else {
			inst, err := x86asm.Decode(buffer[i:], 64)
			if err != nil {
				return nil, fmt.Errorf("error decode the function data: %v", err)
			}

			if inst.Op == x86asm.RET {
				addresses = append(addresses, uint64(i))
			}

			instLen = inst.Len
		}

		i += instLen
	}

	if len(addresses) == 0 {
		return nil, fmt.Errorf("could not found any return addresses")
	}
	log.Debugf("found reuturn addresses of the symbol, symbol: %s, size: %d", symbol, len(addresses))

	var result []link.Link
	for _, address := range addresses {
		l, err := u.addLinkWithType0(symbol, true, p, address)
		if err != nil {
			return nil, err
		}
		result = append(result, l)
		log.Debugf("attach to the return probe of the go program, symbol: %s, addresses: %d", symbol, address)
	}
	return result, nil
}