master ff642a6bcbcb cached
80 files
592.2 KB
182.7k tokens
875 symbols
1 requests
Download .txt
Showing preview only (622K chars total). Download the full file or copy to clipboard to get everything.
Repository: keyval-dev/opentelemetry-go-instrumentation
Branch: master
Commit: ff642a6bcbcb
Files: 80
Total size: 592.2 KB

Directory structure:
gitextract_q11y6zpa/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   └── feature-request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       └── release.yml
├── .gitignore
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── cli/
│   └── main.go
├── docs/
│   ├── design/
│   │   ├── context-propagation.md
│   │   └── manual-instrumentation.md
│   ├── getting-started/
│   │   ├── README.md
│   │   ├── emojivoto/
│   │   │   ├── emoji.yml
│   │   │   ├── kustomization.yml
│   │   │   ├── ns.yml
│   │   │   ├── vote-bot.yml
│   │   │   ├── voting.yml
│   │   │   └── web.yml
│   │   ├── emojivoto-instrumented.yaml
│   │   └── jaeger.yaml
│   └── how-it-works.md
├── go.mod
├── go.sum
├── include/
│   ├── alloc.h
│   ├── arguments.h
│   ├── common.h
│   ├── go_context.h
│   ├── go_types.h
│   ├── libbpf/
│   │   ├── bpf.h
│   │   ├── bpf_core_read.h
│   │   ├── bpf_endian.h
│   │   ├── bpf_helper_defs.h
│   │   ├── bpf_helpers.h
│   │   ├── bpf_tracing.h
│   │   ├── btf.h
│   │   ├── libbpf.h
│   │   ├── libbpf_common.h
│   │   ├── libbpf_legacy.h
│   │   ├── libbpf_version.h
│   │   ├── skel_internal.h
│   │   └── xsk.h
│   ├── span_context.h
│   └── utils.h
└── pkg/
    ├── errors/
    │   └── errors.go
    ├── inject/
    │   ├── data.go
    │   ├── injector.go
    │   └── offset_results.json
    ├── instrumentors/
    │   ├── allocator/
    │   │   └── allocator_linux.go
    │   ├── api.go
    │   ├── bpf/
    │   │   ├── github.com/
    │   │   │   └── gorilla/
    │   │   │       └── mux/
    │   │   │           ├── bpf/
    │   │   │           │   └── probe.bpf.c
    │   │   │           └── probe.go
    │   │   ├── google/
    │   │   │   └── golang/
    │   │   │       └── org/
    │   │   │           └── grpc/
    │   │   │               ├── bpf/
    │   │   │               │   └── probe.bpf.c
    │   │   │               ├── probe.go
    │   │   │               └── server/
    │   │   │                   ├── bpf/
    │   │   │                   │   └── probe.bpf.c
    │   │   │                   └── probe.go
    │   │   └── net/
    │   │       └── http/
    │   │           └── server/
    │   │               ├── bpf/
    │   │               │   └── probe.bpf.c
    │   │               └── probe.go
    │   ├── bpffs/
    │   │   └── bpfsfs.go
    │   ├── context/
    │   │   ├── inst_context.go
    │   │   └── span_context.go
    │   ├── events/
    │   │   └── event.go
    │   ├── manager.go
    │   └── runner.go
    ├── log/
    │   └── logger.go
    ├── opentelemetry/
    │   ├── controller.go
    │   └── id_generator.go
    └── process/
        ├── analyze.go
        ├── args.go
        ├── discover.go
        ├── funcs_nonstripped.go
        ├── funcs_stripped.go
        ├── module.go
        ├── ptrace/
        │   ├── cwrapper_linux.go
        │   ├── ptrace_linux.go
        │   ├── ptrace_linux_amd64.go
        │   └── ptrace_linux_arm64.go
        ├── ret_linux_amd64.go
        └── ret_linux_arm64.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug Report
about: Template for bug reports
labels: kind/bug
---

# Expected Behavior

# Actual Behavior

# Steps to Reproduce the Problem

1.
2.
3.

# Additional Info

- Kubernetes version:

  **Output of `kubectl version`:**

  ```
  (paste your output here)
  ```


- operation-system/kernel version:
  
  **Output of `awk -F '=' '/PRETTY_NAME/ { print $2 }' /etc/os-release`:**
  **Output of `uname -r`:**
  ```
  (paste your output here)
  ```

<!-- Any other additional information -->


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.md
================================================
---
name: Feature Request
about: Template for feature requests
labels: kind/feature
---

### Feature request

<!-- Please describe the feature request and why you would like to have it -->

### Use case

<!-- Please add a concrete use case to demonstrate how such a feature would add value for the user. If you don't have a use case for your feature, please remove this section (however providing a good use case increases the likelihood to be picked up) -->


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
#### What type of this PR
Examples of user facing changes:
- API changes
- Bug fixes
<!-- 
Describe your changes here- ideally you can get that description straight from your descriptive commit message(s)! 

In addition, categorize the changes you're making using the "/kind" Prow command, example:

/kind <kind>

Supported kinds are: bug, cleanup, design, documentation, failing-test, feature, flake, misc, question, tep
-->

#### Which issue(s) this PR fixes:
Fixes #(issue-number)



================================================
FILE: .github/workflows/release.yml
================================================
name: Release
on:
  push:
    tags:
    - 'v*.*.*'
jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
    - name: Set env
      id: vars
      run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v1
    - name: Set up QEMU
      uses: docker/setup-qemu-action@v2
    - name: Login to DockerHub
      uses: docker/login-action@v1 
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}
    - name: Build and push
      uses: docker/build-push-action@v2
      with:
        push: true
        tags: keyval/otel-go-agent:${{ steps.vars.outputs.tag }}
        platforms: linux/amd64,linux/arm64


================================================
FILE: .gitignore
================================================
**/bpf_bpfel.go
**/bpf_bpfel.o
/.idea/
kv-go-instrumentation

================================================
FILE: CONTRIBUTING.md
================================================
# Contributing Guide

- [New Contributor Guide](#contributing-guide)
  - [Ways to Contribute](#ways-to-contribute)
  - [Find an Issue](#find-an-issue)
  - [Ask for Help](#ask-for-help)
  - [Pull Request Lifecycle](#pull-request-lifecycle)
  - [Development Environment Setup](#development-environment-setup)
  - [Sign Your Commits](#sign-your-commits)
  - [Pull Request Checklist](#pull-request-checklist)

Welcome! We are glad that you want to contribute to our project! 💖

As you get started, you are in the best position to give us feedback on areas of
our project that we need help with including:

- Problems found during setting up a new developer environment
- Gaps in our Quickstart Guide or documentation
- Bugs in our automation scripts

If anything doesn't make sense, or doesn't work when you run it, please open a
bug report and let us know!

## Ways to Contribute

We welcome many different types of contributions including:

- New features
- Builds, CI/CD
- Bug fixes
- Documentation
- Issue Triage
- Answering questions on Slack/Mailing List
- Web design
- Communications / Social Media / Blog Posts
- Release management

## Find an Issue

We have good first issues for new contributors and help wanted issues suitable
for any contributor. [good first issue](TODO) has extra information to
help you make your first contribution. [help wanted](TODO) are issues
suitable for someone who isn't a core maintainer and is good to move onto after
your first pull request.

Sometimes there won’t be any issues with these labels. That’s ok! There is
likely still something for you to work on.

Once you see an issue that you'd like to work on, please post a comment saying
that you want to work on it. Something like "I want to work on this" is fine.

## Ask for Help

The best way to reach us with a question when contributing is to ask on:

- The original github issue
- The developer mailing list
- Our Slack channel


================================================
FILE: Dockerfile
================================================
FROM fedora:35 as builder
ARG TARGETARCH
RUN dnf install clang llvm make libbpf-devel -y
RUN curl -LO https://go.dev/dl/go1.18.linux-$TARGETARCH.tar.gz && tar -C /usr/local -xzf go*.linux-$TARGETARCH.tar.gz
ENV PATH="/usr/local/go/bin:${PATH}"
WORKDIR /app
COPY . .
RUN TARGET=$TARGETARCH make build

FROM registry.fedoraproject.org/fedora-minimal:35
COPY --from=builder /app/kv-go-instrumentation /
CMD ["/kv-go-instrumentation"]

================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: Makefile
================================================
# Obtain an absolute path to the directory of the Makefile.
# Assume the Makefile is in the root of the repository.
REPODIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

# Build the list of include directories to compile the bpf program
BPF_INCLUDE += -I${REPODIR}/include/libbpf
BPF_INCLUDE += -I${REPODIR}/include

.PHONY: generate
generate: export CFLAGS := $(BPF_INCLUDE)
generate:
	go mod tidy
	go generate ./...

.PHONY: build
build: generate
	GOOS=linux go build -o kv-go-instrumentation cli/main.go

.PHONY: docker-build
docker-build:
	docker build -t $(IMG) .

================================================
FILE: README.md
================================================
# OpenTelemetry Auto-Instrumentation for Go

This project adds [OpenTelemetry instrumentation](https://opentelemetry.io/docs/concepts/instrumenting/#automatic-instrumentation)
to Go applications without having to modify their source code.
We support a wide range of Go versions (1.12+) and even work on stripped binaries.

Our goal is to provide the same level of automatic instrumentation for Go as exists for languages such as Java and Python.

This automatic instrumentation is based on [eBPF](https://ebpf.io/) uprobes.

For more information, see our [How it works](docs/how-it-works.md) document.

## Getting Started

Check out our [Getting Started on Kubernetes](docs/getting-started/README.md) guide for easily instrumenting your first Go applications.

## Current Instrumentations

| Library/Framework |
| ----------------- |
| net/http - Server |
| gRPC - Client     |
| gRPC - Server     |
| Gorilla Mux       |

## Project Status

This project is actively maintained by [keyval](https://keyval.dev) and is currently in its initial days. We would love to receive your ideas, feedback & contributions.

## Contributing

Please refer to the [contributing.md](CONTRIBUTING.md) file for information about how to get involved. We welcome issues, questions, and pull requests.

## License

This project is licensed under the terms of the Apache 2.0 open source license. Please refer to [LICENSE](LICENSE) for the full terms.


================================================
FILE: cli/main.go
================================================
package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/errors"
	"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/instrumentors"
	"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/log"
	"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/opentelemetry"
	"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/process"
)

func main() {
	err := log.Init()
	if err != nil {
		fmt.Printf("could not init logger: %s\n", err)
		os.Exit(1)
	}
	target := process.ParseTargetArgs()
	if err = target.Validate(); err != nil {
		log.Logger.Error(err, "invalid target args")
		return
	}
	log.Logger.V(0).Info("starting Go OpenTelemetry Agent ...")

	processAnalyzer := process.NewAnalyzer()
	var otelController *opentelemetry.Controller

	if target.Stdout {
		otelController, err = opentelemetry.NewStdoutController()
	} else {
		otelController, err = opentelemetry.NewController()
	}
	if err != nil {
		log.Logger.Error(err, "unable to create OpenTelemetry controller")
		return
	}

	instManager, err := instrumentors.NewManager(otelController)
	if err != nil {
		log.Logger.Error(err, "error creating instrumetors manager")
		return
	}

	stopper := make(chan os.Signal, 1)
	signal.Notify(stopper, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-stopper
		log.Logger.V(0).Info("Got SIGTERM, cleaning up..")
		processAnalyzer.Close()
		instManager.Close()
	}()

	pid, err := processAnalyzer.DiscoverProcessID(target)
	if err != nil {
		if err != errors.ErrInterrupted {
			log.Logger.Error(err, "error while discovering process id")
		}
		return
	}

	targetDetails, err := processAnalyzer.Analyze(pid, instManager.GetRelevantFuncs())
	if err != nil {
		log.Logger.Error(err, "error while analyzing target process")
		return
	}
	log.Logger.V(0).Info("target process analysis completed", "pid", targetDetails.PID,
		"go_version", targetDetails.GoVersion, "dependencies", targetDetails.Libraries,
		"total_functions_found", len(targetDetails.Functions))

	instManager.FilterUnusedInstrumentors(targetDetails)

	log.Logger.V(0).Info("invoking instrumentors")
	err = instManager.Run(targetDetails)
	if err != nil && err != errors.ErrInterrupted {
		log.Logger.Error(err, "error while running instrumentors")
	}
}


================================================
FILE: docs/design/context-propagation.md
================================================
# Design Proposal: Context Propagation

## Motivation

Context propagation is a mechanism that allows tracing to be propagated across process boundaries. Usually, propagation is done by passing traceId and spanId of the current span to the next process. Those identifiers are passed as headers over the requests and responses.

The examples in this proposal describes context propagation over HTTP/gRPC formatted as [W3C Trace Context](https://www.w3.org/TR/trace-context/). However, the implementation should support other transportation methods and header formats.

## Overview

The context propagation implementation should support the following:

1. **Reading headers**: If the current transaction is a part of an existing distributed trace, the request / response should contain headers according to the chosen format.
2. **Storing the current span context**: data about the current span should be stored in an eBPF map to be used by the next process. The suggested data structure is a map from goroutine id to an object similar to [trace.SpanContext](https://pkg.go.dev/go.opentelemetry.io/otel/trace#SpanContext). The current span map should always hold the current running span. Entries can be written by one of the following:

- Header propagator (the use case described in this document) - for remote spans created outside of the current process.
- Automatic instrumentation - for spans created by the automatic instrumentation agent.
- Manual instrumentation - for spans created manually by the user.

3. **Writing headers**: the implementation should get the current span from the eBPF map and propagate it to the next process by adding new headers to the request / response.

Notice that currently, the automatic instrumentation correlates spans to the same trace if they are being executed by the same goroutine. In the future we plan to implement a more robust tracking of the goroutine tree to support traces from multiple goroutines. As part of this planned change, the current implementation of context propagation will also have to be changed (different key in the current span map).

## Example walkthrough

In order to better understand how all the different pieces fit together, we will walk through an example. The example is based on the following scenario:

```mermaid
graph LR
    A[Application A] -->|HTTP| B(Target Application)
    B --->|HTTP| A
    B -->|gRPC| C(Application B)
    C --->|gRPC|B
```

The target application is a simple HTTP server. For every request it receives, it sends a gRPC request to another application. The gRPC response is then sent back to the client. We assume that applications A and B are already instrumented.

#### Step 1: Read request headers

The current HTTP server instrumentation is attached to the following function:

```go
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
```

The instrumentation is already reading fields from the `http.Request` object. Getting the headers should be a matter of tracking the `Header` field in [offsets-tracker](https://github.com/keyval-dev/offsets-tracker) and reading the values according to W3C Trace Context specification.

#### Step 2: Store the headers as current span in the SpanContext map

Update the SpanContext map with key equals to the current gorountine id and value equals to SpanContext object (traceId and spanId).

#### Step 3: Create an HTTP span

Current implementation of HTTP server instrumentor already creates a span for the request. The span traceId and parent spanId should be set according to the values in the eBPF map.

#### Step 4: Update SpanContext map

Update the map with the newly created HTTP span as the current span.

#### Step 5: Add headers to gRPC request

In general, the context propagation implementation should attach a uprobe to a function that writes the headers to the outgoing request.
For example, in gRPC we may choose to attach a uprobe to the following function:

```go
func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.HeaderField, onWrite func()) error
```

The context propagation implementation will use the kernel helper function `bpf_probe_write_user()` in order to modify the `hf` array according to the current span (taken from the eBPF map). Notice that there might be a better choice for the target function, a further investigation is needed.

#### Step 6: Read headers from gRPC response

The implementation will attach a uprobe to a function that reads the headers from the incoming response. Look for headers with keys according to the W3C Trace Context specification. In gRPC example, we may choose to attach a uprobe to the following function:

```go
func decodeMetadataHeader(k, v string) (string, error)
```

This function is located at the `http_util.go` file (again, there may be a better target function, a further investigation is required).

#### Step 7: Update current span map

Similar to step 4, update the current span map with the headers from the previous step.

#### Step 8: Write headers to HTTP response

Similar to step 5, the implementation will attach a uprobe to the function that writes the headers to the response.
A possible candidate may be:

```go
func (h Header) writeSubset(w io.Writer, exclude map[string]bool, trace *httptrace.ClientTrace) error
```

## Proof of Concept

The [following application](https://github.com/edeNFed/ebpf-write-poc) is a test program that demonstrates changing go function arguments via eBPF instrumentation:

```go
func worker(str string) {
	headers := make(map[string]string)
	headers["X-Request-Id"] = str

	fmt.Printf("The Headers are: %s\n", headers)
}

func main() {
	for i := 0; i < 10; i++ {
		worker(fmt.Sprintf("request number: %d", i))
		time.Sleep(2 * time.Second)
	}
}
```

By running a [modified version](https://github.com/edeNFed/opentelemetry-go-instrumentation/tree/ebpf-write-poc) of the automatic instrumentation, we can see that the headers are set by the instrumentation successfully:

```
❯ go run main.go
The Headers are: map[X-Request-Id:request number: 0]
The Headers are: map[X-Request-Id:request number: 1]
The Headers are: map[X-Request-Id:request number: 2]
The Headers are: map[X-Request-Id:request number: 3]
The Headers are: map[X-Request-Id:request number: 4]
The Headers are: map[X-Request-Id:ebpf header value] <--- After instrumentation launched
The Headers are: map[X-Request-Id:ebpf header value]
The Headers are: map[X-Request-Id:ebpf header value]
```

## Safety Considerations

Modifying function arguments has to be done with care. The automatic instrumentation has all the data required in order to fully understand the stack state and safely modify the arguments:

- Strcutres and data fields offsets (tracked over time by version)
- Compiled go version
- CPU architecture

The process of implementing context propagation will include thorough tests to ensure that the implementation is safe.

## Future Work

- Support more propagation formats like B3 and Jaeger.
- Configure propagation via environment variables.


================================================
FILE: docs/design/manual-instrumentation.md
================================================
# Design Proposal: Integration with Manual Instrumentation

## Motivation

Users may want to enrich the traces produced by the automatic instrumentation with additional spans created manually via the [OpenTelemetry Go SDK](https://github.com/open-telemetry/opentelemetry-go).

## Overview

Integration with manual instrumentation happens in two steps:

1. **Modify spans created manually** - attach a uprobe to the function that creates the span, override the trace id and parent span id with the current active span (according to the eBPF map described in the context propagation document).
2. **Update active span map** - After the span is created, update the eBPF map with the new span as the current span. This step is needed in order to create traces that combines spans created manually, automatically (via other instrumentors) and remotely (via context propagation).

This implementation depends on changes described in the [Context Propagation design document](context-propagation.md) and can't be implemented before context propagation is implemented.

## Instrumenting OpenTelemetry Go SDK

The following function (located in `tracer.go` file) may be a good candidate for instrumenting the creation of manual spans:

```go
func (tr *tracer) newRecordingSpan(psc, sc trace.SpanContext, name string, sr SamplingResult, config *trace.SpanConfig) *recordingSpan {
```

By overriding `psc.spanID` and `sc.traceID` to match the current span according to the eBPF map, the function will create a span that is a child of the current active span.

## Future Work

### Use single exporter

Applications instrumented both manually and automatically will export the produced spans via two different exporters. One created manually by the user and another one created in the instrumentation agent. This is not damaging the combined traces, but it is not ideal. In the future, we may want to implement an exporter that communicates with the instrumentation agent (via mechanisem like Unix domain socket) and exports the combined traces over a single connection.


================================================
FILE: docs/getting-started/README.md
================================================
# Getting Started with Go OpenTelemetry Automatic Instrumentation

In this tutorial, we will walk through how to get started with instrumenting the [emojivoto](https://github.com/BuoyantIO/emojivoto) application, a well known microservice example running locally on a Kubernetes cluster.

## Before you begin

The following tools are required to run this tutorial:

- [Kind](https://kind.sigs.k8s.io/) to run a local Kubernetes cluster with Docker container nodes.
- [Kubernetes CLI (kubectl)](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to run commands against Kubernetes clusters.

## Creating the Kubernetes cluster

Create a new local Kubernetes cluster, by running the following command:

```shell
kind create cluster
```

## Deployment

The Kubernetes cluster will run the emojivoto applications and a jaeger UI for visualizing the OpenTelemetry traces:

![Deployed Applications](deployed_apps.jpg)

The different emojivoto applications are communicating via gRPC. Instrumenting those applications would allow us to view the gRPC requests between the applications.

### Deploying the emojivoto application

Run the following command:

```shell
kubectl apply -k github.com/keyval-dev/opentelemetry-go-instrumentation/docs/getting-started/emojivoto
```

### Deploying Jaeger UI

Install Jaeger UI by running:

```shell
kubectl apply -f https://raw.githubusercontent.com/keyval-dev/opentelemetry-go-instrumentation/master/docs/getting-started/jaeger.yaml -n emojivoto
```

This command installs Jaeger as a new Deployment and an additional Service that we will use later for accessing the Jaeger UI.

In a real world application, you would probably want to send the tracing data to [OpenTelemetry collector](https://github.com/open-telemetry/opentelemetry-collector) instead of directly to Jaeger.

## Instrumentation

Apply the automatic instrumentation to the `emoji`, `voting`, and `web` applications by executing the following command:

```shell
kubectl apply -f https://raw.githubusercontent.com/keyval-dev/opentelemetry-go-instrumentation/master/docs/getting-started/emojivoto-instrumented.yaml -n emojivoto
```

## Perform actions on the target Application

Now all that left to do is to perform some actions on the target application that will cause the creation of detailed distributed traces.

Port forward to the frontend service:

```shell
kubectl port-forward svc/web-svc 8080:80 -n emojivoto
```

Go to `http://localhost:8080`, and click the **view the leaderboard** button.

## Viewing the traces

First, port forward to the Jaeger UI:

```shell
kubectl port-forward svc/jaeger 16686:16686 -n emojivoto
```

Then, open the Jaeger UI in your browser by navigating to http://localhost:16686/

After selecting the `emojivoto-web` service, you should see the following traces:
![Traces](jaeger_traces.png)

Let's start with a simple trace, click on one of the `/api/vote` traces, you should see something like the following:
![vote_trace](vote_trace.png)

A few things worth noticing in this trace:
- **In process context-propagation**: We can see that the `web` application got an HTTP request (the root span) which caused two sequential gRPC requests to the `emoji` and `voting` services.
- **Cross process context-propagation**: The automatic instrumentation adds the relevant headers to gRPC / HTTP requests in order to make traces distributed across processes. In Jaeger, different applications are marked in different colors.
- **Extremely low overhead**: The entire trace took 3.1 milliseconds to complete. This show that using eBPF for instrumentation adds extremely low overhead.
- **Following OpenTelemetry Specifications**: You can click on any span in the trace to view the different attributes. All the spans produced by the automatic instrumentation follows the OpenTelemetry specification and therefore will work with any OpenTelemetry compatible backend.

Now we will view a more complex trace, search for traces for the `/api/leaderboard` endpoint.
You can quickly find them by clicking on the points with the highest duration in Jaeger's main screen.
![leaderboard_trace](leaderboard_trace.png)
We can get a pretty good understanding of how the leaderboard feature works by looking at this trace:
- First, the web service will perform a gRPC request to the `voting` service to get a list of the available emojis.
- Second, The web service will loop over the received list of emojis and for every item on the list it will perform a gRPC request to the `emoji` service to get the amount of votes for the current item.
- As you can see this happens sequentially, which is one of the reason the leaderboard endpoint takes about 150ms to complete.

### Notice that we did not change any application code to get those traces, we are using the exact same containers from the emojivoto project.

## Next Steps

The easiest way to apply this automatic instrumentation for any application is by using a control plane such as [Odigos](https://github.com/keyval-dev/odigos).

For more details visit the [Odigos website](https://odigos.io).

## Cleanup

Delete the Kubernetes cluster:

```shell
kind delete cluster
```


================================================
FILE: docs/getting-started/emojivoto/emoji.yml
================================================
kind: ServiceAccount
apiVersion: v1
metadata:
  name: emoji
  namespace: emojivoto
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: emoji
  namespace: emojivoto
  labels:
    app.kubernetes.io/name: emoji
    app.kubernetes.io/part-of: emojivoto
    app.kubernetes.io/version: v11
spec:
  replicas: 1
  selector:
    matchLabels:
      app: emoji-svc
      version: v11
  template:
    metadata:
      labels:
        app: emoji-svc
        version: v11
    spec:
      serviceAccountName: emoji
      terminationGracePeriodSeconds: 0
      containers:
      - env:
        - name: GRPC_PORT
          value: "8080"
        - name: PROM_PORT
          value: "8801"
        image: docker.l5d.io/buoyantio/emojivoto-emoji-svc:v11
        name: emoji-svc
        ports:
        - containerPort: 8080
          name: grpc
        - containerPort: 8801
          name: prom
        resources:
          requests:
            cpu: 100m
---
apiVersion: v1
kind: Service
metadata:
  name: emoji-svc
  namespace: emojivoto
spec:
  selector:
    app: emoji-svc
  ports:
  - name: grpc
    port: 8080
    targetPort: 8080
  - name: prom
    port: 8801
    targetPort: 8801


================================================
FILE: docs/getting-started/emojivoto/kustomization.yml
================================================
resources:
- ns.yml
- web.yml
- emoji.yml
- voting.yml
- vote-bot.yml


================================================
FILE: docs/getting-started/emojivoto/ns.yml
================================================
apiVersion: v1
kind: Namespace
metadata:
  name: emojivoto


================================================
FILE: docs/getting-started/emojivoto/vote-bot.yml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vote-bot
  namespace: emojivoto
  labels:
    app.kubernetes.io/name: vote-bot
    app.kubernetes.io/part-of: emojivoto
    app.kubernetes.io/version: v11
spec:
  replicas: 1
  selector:
    matchLabels:
      app: vote-bot
      version: v11
  template:
    metadata:
      labels:
        app: vote-bot
        version: v11
    spec:
      containers:
      - command:
        - emojivoto-vote-bot
        env:
        - name: WEB_HOST
          value: web-svc.emojivoto:80
        image: docker.l5d.io/buoyantio/emojivoto-web:v11
        name: vote-bot
        resources:
          requests:
            cpu: 10m


================================================
FILE: docs/getting-started/emojivoto/voting.yml
================================================
kind: ServiceAccount
apiVersion: v1
metadata:
  name: voting
  namespace: emojivoto
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: voting
  namespace: emojivoto
  labels:
    app.kubernetes.io/name: voting
    app.kubernetes.io/part-of: emojivoto
    app.kubernetes.io/version: v11
spec:
  replicas: 1
  selector:
    matchLabels:
      app: voting-svc
      version: v11
  template:
    metadata:
      labels:
        app: voting-svc
        version: v11
    spec:
      serviceAccountName: voting
      terminationGracePeriodSeconds: 0
      containers:
      - env:
        - name: GRPC_PORT
          value: "8080"
        - name: PROM_PORT
          value: "8801"
        image: docker.l5d.io/buoyantio/emojivoto-voting-svc:v11
        name: voting-svc
        ports:
        - containerPort: 8080
          name: grpc
        - containerPort: 8801
          name: prom
        resources:
          requests:
            cpu: 100m
---
apiVersion: v1
kind: Service
metadata:
  name: voting-svc
  namespace: emojivoto
spec:
  selector:
    app: voting-svc
  ports:
  - name: grpc
    port: 8080
    targetPort: 8080
  - name: prom
    port: 8801
    targetPort: 8801


================================================
FILE: docs/getting-started/emojivoto/web.yml
================================================
kind: ServiceAccount
apiVersion: v1
metadata:
  name: web
  namespace: emojivoto
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: emojivoto
  labels:
    app.kubernetes.io/name: web
    app.kubernetes.io/part-of: emojivoto
    app.kubernetes.io/version: v11
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-svc
      version: v11
  template:
    metadata:
      labels:
        app: web-svc
        version: v11
    spec:
      serviceAccountName: web
      terminationGracePeriodSeconds: 0
      containers:
      - env:
        - name: WEB_PORT
          value: "8080"
        - name: EMOJISVC_HOST
          value: emoji-svc.emojivoto:8080
        - name: VOTINGSVC_HOST
          value: voting-svc.emojivoto:8080
        - name: INDEX_BUNDLE
          value: dist/index_bundle.js
        image: docker.l5d.io/buoyantio/emojivoto-web:v11
        name: web-svc
        ports:
        - containerPort: 8080
          name: http
        resources:
          requests:
            cpu: 100m
---
apiVersion: v1
kind: Service
metadata:
  name: web-svc
  namespace: emojivoto
spec:
  type: ClusterIP
  selector:
    app: web-svc
  ports:
  - name: http
    port: 80
    targetPort: 8080


================================================
FILE: docs/getting-started/emojivoto-instrumented.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
  name: emoji
  namespace: emojivoto
  labels:
    app.kubernetes.io/name: emoji
    app.kubernetes.io/part-of: emojivoto
    app.kubernetes.io/version: v11
spec:
  replicas: 1
  selector:
    matchLabels:
      app: emoji-svc
      version: v11
  template:
    metadata:
      labels:
        app: emoji-svc
        version: v11
    spec:
      serviceAccountName: emoji
      shareProcessNamespace: true
      terminationGracePeriodSeconds: 0
      initContainers:
        - name: copy-launcher
          image: keyval/launcher:v0.1
          command:
            - cp
            - -a
            - /kv-launcher/.
            - /odigos-launcher/
          volumeMounts:
            - name: launcherdir
              mountPath: /odigos-launcher
      containers:
        - env:
            - name: GRPC_PORT
              value: "8080"
            - name: PROM_PORT
              value: "8801"
          image: docker.l5d.io/buoyantio/emojivoto-emoji-svc:v11
          name: emoji-svc
          command:
            - /odigos-launcher/launch
            - /usr/local/bin/emojivoto-emoji-svc
          volumeMounts:
            - mountPath: /odigos-launcher
              name: launcherdir
          ports:
            - containerPort: 8080
              name: grpc
            - containerPort: 8801
              name: prom
          resources:
            requests:
              cpu: 100m
        - name: emojivoto-emoji-instrumentation
          image: keyval/otel-go-agent:v0.6.0
          env:
            - name: OTEL_TARGET_EXE
              value: /usr/local/bin/emojivoto-emoji-svc
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "jaeger:4317"
            - name: OTEL_SERVICE_NAME
              value: "emojivoto-emoji"
          securityContext:
            runAsUser: 0
            capabilities:
              add:
                - SYS_PTRACE
            privileged: true
          volumeMounts:
            - mountPath: /sys/kernel/debug
              name: kernel-debug
      volumes:
        - name: launcherdir
          emptyDir: {}
        - name: kernel-debug
          hostPath:
            path: /sys/kernel/debug
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: voting
  namespace: emojivoto
  labels:
    app.kubernetes.io/name: voting
    app.kubernetes.io/part-of: emojivoto
    app.kubernetes.io/version: v11
spec:
  replicas: 1
  selector:
    matchLabels:
      app: voting-svc
      version: v11
  template:
    metadata:
      labels:
        app: voting-svc
        version: v11
    spec:
      serviceAccountName: voting
      shareProcessNamespace: true
      terminationGracePeriodSeconds: 0
      initContainers:
        - name: copy-launcher
          image: keyval/launcher:v0.1
          command:
            - cp
            - -a
            - /kv-launcher/.
            - /odigos-launcher/
          volumeMounts:
            - name: launcherdir
              mountPath: /odigos-launcher
      containers:
        - env:
            - name: GRPC_PORT
              value: "8080"
            - name: PROM_PORT
              value: "8801"
          image: docker.l5d.io/buoyantio/emojivoto-voting-svc:v11
          name: voting-svc
          command:
            - /odigos-launcher/launch
            - /usr/local/bin/emojivoto-voting-svc
          volumeMounts:
            - mountPath: /odigos-launcher
              name: launcherdir
          ports:
            - containerPort: 8080
              name: grpc
            - containerPort: 8801
              name: prom
          resources:
            requests:
              cpu: 100m
        - name: emojivoto-voting-instrumentation
          image: keyval/otel-go-agent:v0.6.0
          env:
            - name: OTEL_TARGET_EXE
              value: /usr/local/bin/emojivoto-voting-svc
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "jaeger:4317"
            - name: OTEL_SERVICE_NAME
              value: "emojivoto-voting"
          securityContext:
            runAsUser: 0
            capabilities:
              add:
                - SYS_PTRACE
            privileged: true
          volumeMounts:
            - mountPath: /sys/kernel/debug
              name: kernel-debug
      volumes:
        - name: launcherdir
          emptyDir: {}
        - name: kernel-debug
          hostPath:
            path: /sys/kernel/debug
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: emojivoto
  labels:
    app.kubernetes.io/name: web
    app.kubernetes.io/part-of: emojivoto
    app.kubernetes.io/version: v11
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-svc
      version: v11
  template:
    metadata:
      labels:
        app: web-svc
        version: v11
    spec:
      serviceAccountName: web
      shareProcessNamespace: true
      terminationGracePeriodSeconds: 0
      initContainers:
        - name: copy-launcher
          image: keyval/launcher:v0.1
          command:
            - cp
            - -a
            - /kv-launcher/.
            - /odigos-launcher/
          volumeMounts:
            - name: launcherdir
              mountPath: /odigos-launcher
      containers:
        - env:
            - name: WEB_PORT
              value: "8080"
            - name: EMOJISVC_HOST
              value: emoji-svc.emojivoto:8080
            - name: VOTINGSVC_HOST
              value: voting-svc.emojivoto:8080
            - name: INDEX_BUNDLE
              value: dist/index_bundle.js
          image: docker.l5d.io/buoyantio/emojivoto-web:v11
          name: web-svc
          command:
            - /odigos-launcher/launch
            - /usr/local/bin/emojivoto-web
          volumeMounts:
            - mountPath: /odigos-launcher
              name: launcherdir
          ports:
            - containerPort: 8080
              name: http
          resources:
            requests:
              cpu: 100m
        - name: emojivoto-web-instrumentation
          image: keyval/otel-go-agent:v0.6.0
          env:
            - name: OTEL_TARGET_EXE
              value: /usr/local/bin/emojivoto-web
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "jaeger:4317"
            - name: OTEL_SERVICE_NAME
              value: "emojivoto-web"
          securityContext:
            runAsUser: 0
            capabilities:
              add:
                - SYS_PTRACE
            privileged: true
          volumeMounts:
            - mountPath: /sys/kernel/debug
              name: kernel-debug
      volumes:
        - name: launcherdir
          emptyDir: {}
        - name: kernel-debug
          hostPath:
            path: /sys/kernel/debug

================================================
FILE: docs/getting-started/jaeger.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: jaeger
  name: jaeger
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jaeger
  template:
    metadata:
      labels:
        app: jaeger
    spec:
      containers:
      - image: jaegertracing/opentelemetry-all-in-one:latest
        name: opentelemetry-all-in-one
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: jaeger
  name: jaeger
spec:
  ports:
  - name: grpc
    port: 4317
    targetPort: 4317
  - name: ui
    port: 16686
    targetPort: 16686
  selector:
    app: jaeger


================================================
FILE: docs/how-it-works.md
================================================
# OpenTelemtry Go Instrumentation - How it works

We aim to bring the automatic instrumentation experience found in languages like [Java](https://github.com/open-telemetry/opentelemetry-java-instrumentation), [Python](https://github.com/open-telemetry/opentelemetry-python-contrib) and [JavaScript](https://github.com/open-telemetry/opentelemetry-js-contrib) to Go applications.

## Design Goals

- No code changes required - any Go application can be instrumented without modifying the source code.
- Support wide range of Go applications - instrumentation is supported for Go version 1.12 and above. In addition, a common practice for Go applications is to shrink the binary size by stripping debug symbols via `go build -ldflags "-s -w"`. This instrumentation works for stripped binaries as well.
- Configuration is done via `OTEL_*` environment variables according to [OpenTelemetry Environment Variable Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md#general-sdk-configuration)
- Instrumented libraries follow the [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification) and semantic conventions to produce standard OpenTelemetry data.

## Why eBPF

Go is a compiled language. Unlike languages such as Java and Python, Go compiles natively to machine code. This makes it impossible to add additional code at runtime to instrument Go applications.
Fortunately, the Linux kernel provides a mechanism to attach user-defined code to the execution of a process. This is called [eBPF](https://ebpf.io/) and it is widely used in other Cloud Native projects such as Cilium and Falco.

## Main Challenges and How We Overcome Them

Using eBPF to instrument Go applications is non-trivial. In the following sections we will describe the main challenges and how we solved them.

### Instrumentation Stability

eBPF programs access user code and variables by analyzing the stack and the CPU registers. For example, to read the value of the `target` field in the `google.golang.org/grpc.ClientConn` struct (see gRPC instrumentor for an example), the eBPF program needs to know the offset of the field inside the struct. The offset is determined by the field location inside the struct definition.

Hard coding this offset information into the eBPF programs creates a very unstable instrumentation. Fields locations inside structs are subject to change and the eBPF program needs to be recompiled every time the struct definition changes.
Luckily for us, there is a way to analyze the target binary and extract the required offsets, by using DWARF. The DWARF debug information is generated by the compiler and is stored inside the binary.

Notice that one of our design goals is to support stripped Go binaries - meaning binaries that do not contain debug information. In order to support stripped binaries and to create a stable instrumentation, we created a library called [offsets-tracker](https://github.com/keyval-dev/offsets-tracker). This library tracks the offset of different fields across versions.

We currently track instrumented structs inside the Go standard library and selected open source packages. This solution does not require DWARF information on the target binary and provides stability to instrumentations. Instrumentation authors can get a field location by name instead of hard coding a field offset.

The offsets-tracker generates the [offset_results.json](https://github.com/keyval-dev/opentelemetry-go-instrumentation/blob/master/pkg/inject/offset_results.json) file. This file contains the offsets of the fields in the instrumented structs.

### Uretprobes

One of the basic requirments of OpenTelemetry spans is to contain start timestamp and end timestamp. Getting those timestamps is possible by placing an eBPF code at the start and the end of the instrumented function. eBPF supports this requirement via uprobes and uretprobes. Uretprobes are used to invoke eBPF code at the end of the function. Unfortunately, uretprobes and Go [do not play well together](https://github.com/golang/go/issues/22008).

We overcome this issue by analyzing the target binary and detecting all the return statements in the instrumented functions. We then place a uprobe at the end of each return statement. This uprobe invokes the eBPF code that collects the end timestamp.

### Timestamp tracking

eBPF programs can access the current timestamp by calling `bpf_ktime_get_ns()`. The value returned by this function is fetched from the `CLOCK_MONOTONIC` clock and represents the number of nanoseconds since the system boot time.

According to OpenTelemetry specification start time and end time should be timestamps and represent exact point in time. Converting from monotonic time to epoch timestamp is automatically handled by this library. Conversion is achieved by discovering the epoch boot time and adding it to the monotonic time collected by the eBPF program.

### Support Go 1.17 and above

Since version 1.17 and above, Go [changed the way it passes arguments to functions](https://go.googlesource.com/go/+/refs/heads/dev.regabi/src/cmd/compile/internal-abi.md#function-call-argument-and-result-passing).
Prior to version 1.17, Go placed arguments in the stack in the order they were defined in the function signature. Version 1.17 and above uses the machine registers to pass arguments.

We overcome this by analyzing the target binary and detecting the compiled Go version. If the compiled Go version is 1.17 or above, we read arguments from the machine registers. If the compiled Go version is below 1.17, we read arguments from the stack. This should be transparent to the instrumentation authors and abstracted by a function named `get_argument()`.


================================================
FILE: go.mod
================================================
module github.com/keyval-dev/opentelemetry-go-instrumentation

go 1.18

require (
	github.com/cilium/ebpf v0.8.0
	github.com/go-logr/logr v1.2.3
	github.com/go-logr/zapr v1.2.2
	github.com/hashicorp/go-version v1.4.0
	github.com/prometheus/procfs v0.8.0
	go.opentelemetry.io/otel v1.11.1
	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.8.0
	go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.1
	go.opentelemetry.io/otel/sdk v1.11.1
	go.opentelemetry.io/otel/trace v1.11.1
	go.uber.org/zap v1.20.0
	golang.org/x/arch v0.0.0-20210923205945-b76863e36670
	golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8
	google.golang.org/grpc v1.46.2
)

require (
	github.com/cenkalti/backoff/v4 v4.1.3 // indirect
	github.com/go-logr/stdr v1.2.2 // indirect
	github.com/golang/protobuf v1.5.2 // indirect
	github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
	go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.8.0 // indirect
	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.8.0 // indirect
	go.opentelemetry.io/proto/otlp v0.18.0 // indirect
	go.uber.org/atomic v1.7.0 // indirect
	go.uber.org/multierr v1.6.0 // indirect
	golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
	golang.org/x/text v0.3.5 // indirect
	google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect
	google.golang.org/protobuf v1.28.0 // indirect
)


================================================
FILE: go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cilium/ebpf v0.8.0 h1:2V6KSg3FRADVU2BMIRemZ0hV+9OM+aAHhZDjQyjJTAs=
github.com/cilium/ebpf v0.8.0/go.mod h1:f5zLIM0FSNuAkSyLAN7X+Hy6yznlF1mNiWUMfxMtrgk=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.2.2 h1:5YNlIL6oZLydaV4dOFjL8YpgXF/tPeTbnpatnu3cq6o=
github.com/go-logr/zapr v1.2.2/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4=
github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v1.11.1 h1:4WLLAmcfkmDk2ukNXJyq3/kiz/3UzCaYq6PskJsaou4=
go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.8.0 h1:ao8CJIShCaIbaMsGxy+jp2YHSudketpDgDRcbirov78=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.8.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.8.0 h1:LrHL1A3KqIgAgi6mK7Q0aczmzU414AONAGT5xtnp+uo=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.8.0/go.mod h1:w8aZL87GMOvOBa2lU/JlVXE1q4chk/0FX+8ai4513bw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.8.0 h1:00hCSGLIxdYK/Z7r8GkaX0QIlfvgU3tmnLlQvcnix6U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.8.0/go.mod h1:twhIvtDQW2sWP1O2cT1N8nkSBgKCRZv2z6COTTBrf8Q=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.1 h1:3Yvzs7lgOw8MmbxmLRsQGwYdCubFmUHSooKaEhQunFQ=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.11.1/go.mod h1:pyHDt0YlyuENkD2VwHsiRDf+5DfI3EH7pfhUYW6sQUE=
go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs=
go.opentelemetry.io/otel/sdk v1.11.1/go.mod h1:/l3FE4SupHJ12TduVjUkZtlfFqDCQJlOlithYrdktys=
go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ=
go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.18.0 h1:W5hyXNComRa23tGpKwG+FRAc4rfF6ZUg1JReK+QHS80=
go.opentelemetry.io/proto/otlp v0.18.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.20.0 h1:N4oPlghZwYG55MlU6LXk/Zp00FVNE9X9wrYO8CEs4lc=
go.uber.org/zap v1.20.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RAc5XyaeamM+0VHRd4lc=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=


================================================
FILE: include/alloc.h
================================================
#include "bpf_helpers.h"

#define MAX_ENTRIES 50

// Injected in init
volatile const u32 total_cpus;
volatile const u64 start_addr;
volatile const u64 end_addr;

struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
	__type(key, s32);
	__type(value, u64);
	__uint(max_entries, MAX_ENTRIES);
	__uint(pinning, LIBBPF_PIN_BY_NAME);
} alloc_map SEC(".maps");

static __always_inline u64 get_area_start() {
    s64 partition_size = (end_addr - start_addr) / total_cpus;
    u32 current_cpu = bpf_get_smp_processor_id();
    s32 start_index = 0;
    u64* start = (u64*) bpf_map_lookup_elem(&alloc_map, &start_index);
    if (start == NULL || *start == 0) {
        u64 current_start_addr = start_addr + (partition_size * current_cpu);
        bpf_map_update_elem(&alloc_map, &start_index, &current_start_addr, BPF_ANY);
        return current_start_addr;
    } else {
        return *start;
    }
}

static __always_inline u64 get_area_end(u64 start) {
    s64 partition_size = (end_addr - start_addr) / total_cpus;
    s32 end_index = 1;
    bpf_printk("total size: %d, partition size: %d, modulo: %d", end_addr - start_addr, partition_size, (end_addr - start_addr) % partition_size);
    u64* end = (u64*)bpf_map_lookup_elem(&alloc_map, &end_index);
    if (end == NULL || *end == 0) {
        u64 current_end_addr = start + partition_size;
        bpf_map_update_elem(&alloc_map, &end_index, &current_end_addr, BPF_ANY);
        return current_end_addr;
    } else {
        return *end;
    }
}

static __always_inline void* write_target_data(void* data, s32 size) {
    if (!data || data == NULL) {
        return NULL;
    }

    u64 start = get_area_start();
    u64 end = get_area_end(start);
    s32 current_cpu = bpf_get_smp_processor_id();
    if (end - start < size) {
        bpf_printk("reached end of CPU memory block, going to the start again");
        s32 start_index = 0;
        bpf_map_delete_elem(&alloc_map, &start_index);
        start = get_area_start();
    }

    void* target = (void*)start;
    long success = bpf_probe_write_user(target, data, size);
    if (success == 0) {
        s32 start_index = 0;
        u64 updated_start = start + size;

        // align updated_start to 8 bytes
        if (updated_start % 8 != 0) {
            updated_start += 8 - (updated_start % 8);
        }

        bpf_map_update_elem(&alloc_map, &start_index, &updated_start, BPF_ANY);
        return target;
    }

    bpf_printk("failed to write to userspace, error code: %d, addr: %lx", success, target);
    return NULL;
}

================================================
FILE: include/arguments.h
================================================
#include "common.h"
#include "bpf_tracing.h"
#include "bpf_helpers.h"
#include <stdbool.h>

// Injected in init
volatile const bool is_registers_abi;

void* get_argument_by_reg(struct pt_regs *ctx, int index) {
    switch (index) {
        case 1:
            return (void*)GO_PARAM1(ctx);
        case 2:
            return (void*)GO_PARAM2(ctx);
        case 3:
            return (void*)GO_PARAM3(ctx);
        case 4:
            return (void*)GO_PARAM4(ctx);
        case 5:
            return (void*)GO_PARAM5(ctx);
        case 6:
            return (void*)GO_PARAM6(ctx);
        case 7:
            return (void*)GO_PARAM7(ctx);
        case 8:
            return (void*)GO_PARAM8(ctx);
        case 9:
            return (void*)GO_PARAM9(ctx);
        default:
            return NULL;
    }
}

void* get_argument_by_stack(struct pt_regs *ctx, int index) {
    void* ptr = 0;
    bpf_probe_read(&ptr, sizeof(ptr), (void *)(PT_REGS_SP(ctx)+(index*8)));
    return ptr;
}

void* get_argument(struct pt_regs *ctx, int index) {
    if (is_registers_abi) {
        return get_argument_by_reg(ctx, index);
    }

    return get_argument_by_stack(ctx, index);
}

================================================
FILE: include/common.h
================================================
// This is a compact version of `vmlinux.h`

#define MAX_OS_THREADS 20

#ifndef __VMLINUX_H__
#define __VMLINUX_H__

typedef unsigned char __u8;
typedef short int __s16;
typedef short unsigned int __u16;
typedef int __s32;
typedef unsigned int __u32;
typedef long long int __s64;
typedef long long unsigned int __u64;
typedef __u8 u8;
typedef __s16 s16;
typedef __u16 u16;
typedef __s32 s32;
typedef __u32 u32;
typedef __s64 s64;
typedef __u64 u64;
typedef __u16 __le16;
typedef __u16 __be16;
typedef __u32 __be32;
typedef __u64 __be64;
typedef __u32 __wsum;

enum bpf_map_type {
	BPF_MAP_TYPE_UNSPEC = 0,
	BPF_MAP_TYPE_HASH = 1,
	BPF_MAP_TYPE_ARRAY = 2,
	BPF_MAP_TYPE_PROG_ARRAY = 3,
	BPF_MAP_TYPE_PERF_EVENT_ARRAY = 4,
	BPF_MAP_TYPE_PERCPU_HASH = 5,
	BPF_MAP_TYPE_PERCPU_ARRAY = 6,
	BPF_MAP_TYPE_STACK_TRACE = 7,
	BPF_MAP_TYPE_CGROUP_ARRAY = 8,
	BPF_MAP_TYPE_LRU_HASH = 9,
	BPF_MAP_TYPE_LRU_PERCPU_HASH = 10,
	BPF_MAP_TYPE_LPM_TRIE = 11,
	BPF_MAP_TYPE_ARRAY_OF_MAPS = 12,
	BPF_MAP_TYPE_HASH_OF_MAPS = 13,
	BPF_MAP_TYPE_DEVMAP = 14,
	BPF_MAP_TYPE_SOCKMAP = 15,
	BPF_MAP_TYPE_CPUMAP = 16,
	BPF_MAP_TYPE_XSKMAP = 17,
	BPF_MAP_TYPE_SOCKHASH = 18,
	BPF_MAP_TYPE_CGROUP_STORAGE = 19,
	BPF_MAP_TYPE_REUSEPORT_SOCKARRAY = 20,
	BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE = 21,
	BPF_MAP_TYPE_QUEUE = 22,
	BPF_MAP_TYPE_STACK = 23,
	BPF_MAP_TYPE_SK_STORAGE = 24,
	BPF_MAP_TYPE_DEVMAP_HASH = 25,
	BPF_MAP_TYPE_STRUCT_OPS = 26,
	BPF_MAP_TYPE_RINGBUF = 27,
	BPF_MAP_TYPE_INODE_STORAGE = 28,
};

enum {
	BPF_ANY = 0,
	BPF_NOEXIST = 1,
	BPF_EXIST = 2,
	BPF_F_LOCK = 4,
};

/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and
 * BPF_FUNC_perf_event_read_value flags.
 */
#define BPF_F_INDEX_MASK 0xffffffffULL
#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK

#if defined(__TARGET_ARCH_x86)
struct pt_regs {
	long unsigned int r15;
	long unsigned int r14;
	long unsigned int r13;
	long unsigned int r12;
	long unsigned int bp;
	long unsigned int bx;
	long unsigned int r11;
	long unsigned int r10;
	long unsigned int r9;
	long unsigned int r8;
	long unsigned int ax;
	long unsigned int cx;
	long unsigned int dx;
	long unsigned int si;
	long unsigned int di;
	long unsigned int orig_ax;
	long unsigned int ip;
	long unsigned int cs;
	long unsigned int flags;
	long unsigned int sp;
	long unsigned int ss;
};
#elif defined(__TARGET_ARCH_arm64)
struct user_pt_regs {
	__u64 regs[31];
	__u64 sp;
	__u64 pc;
	__u64 pstate;
};

struct pt_regs {
	union {
		struct user_pt_regs user_regs;
		struct {
			u64 regs[31];
			u64 sp;
			u64 pc;
			u64 pstate;
		};
	};
	u64 orig_x0;
	s32 syscallno;
	u32 unused2;
	u64 orig_addr_limit;
	u64 pmr_save;
	u64 stackframe[2];
	u64 lockdep_hardirqs;
	u64 exit_rcu;
};
#endif

#endif /* __VMLINUX_H__ */

================================================
FILE: include/go_context.h
================================================
#include "bpf_helpers.h"

#define MAX_DISTANCE 10

static __always_inline void* find_context_in_map(void *ctx, void *context_map) {
    void *data = ctx;
    for (int i = 0; i < MAX_DISTANCE; i++) {
        void* found_in_map = bpf_map_lookup_elem(context_map, &data);
        if (found_in_map != NULL) {
            return data;
        }

        // We assume context.Context implementation containens Parent context.Context member
        // Since the parent is also an interface, we need to read the data part of it
        bpf_probe_read(&data, sizeof(data), data+8);
    }

    bpf_printk("context %lx not found in context map", ctx);
    return NULL;
}

================================================
FILE: include/go_types.h
================================================
#include "alloc.h"
#include "bpf_helpers.h"

#define MAX_REALLOCATION 400
#define MAX_DATA_SIZE 400

struct go_string {
    char* str;
    s32 len;
};

struct go_slice {
    void* array;
    s32 len;
    s32 cap;
};

struct go_slice_user_ptr {
    void* array;
    void* len;
    void* cap;
};

struct go_iface {
    void* tab;
    void* data;
};

static __always_inline struct go_string write_user_go_string(char* str, u32 len) {
    // Copy chars to userspace
    char *addr = write_target_data((void*)str, len);

    // Build string struct in kernel space
    struct go_string new_string = {};
    new_string.str = addr;
    new_string.len = len;

    // Copy new string struct to userspace
    void* res = write_target_data((void*)&new_string, sizeof(new_string));
    if (res == NULL) {
        new_string.len = 0;
    }

    return new_string;
}

static __always_inline void append_item_to_slice(struct go_slice *slice, void* new_item, s32 item_size, struct go_slice_user_ptr *slice_user_ptr, void* buff) {
    if (slice->len < slice->cap) {
        // Room available on current array
        bpf_probe_write_user(slice->array+(item_size*slice->len), new_item, item_size);
    } else {
        // No room on current array - copy to new one of size item_size * (len + 1)
        if (slice->len > MAX_DATA_SIZE || slice->len < 1) {
            return;
        }

        s32 alloc_size = item_size * slice->len;
        s32 bounded_alloc_size = alloc_size > MAX_REALLOCATION ? MAX_REALLOCATION : (alloc_size < 1 ? 1 : alloc_size);

        // Get buffer
        s32 index = 0;
        void* map_buff = bpf_map_lookup_elem(buff, &index);
        if (!map_buff) {
            return;
        }

        // Append to buffer
        bpf_probe_read_user(map_buff, bounded_alloc_size, slice->array);
        bpf_probe_read(map_buff+bounded_alloc_size, item_size, new_item);

        // Copy buffer to userspace
        u32 new_array_size = bounded_alloc_size+item_size;
        if (new_array_size > MAX_DATA_SIZE || new_array_size < 1) {
            return;
        }

        void* new_array = write_target_data(map_buff, new_array_size);

        // Update array
        slice->array = new_array;
        long success = bpf_probe_write_user(slice_user_ptr->array, &slice->array, sizeof(slice->array));

        // Update cap
        slice->cap++;
        success = bpf_probe_write_user(slice_user_ptr->cap, &slice->cap, sizeof(slice->cap));
    }

    // Update len
    slice->len++;
    long success = bpf_probe_write_user(slice_user_ptr->len, &slice->len, sizeof(slice->len));
}

================================================
FILE: include/libbpf/bpf.h
================================================
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */

/*
 * common eBPF ELF operations.
 *
 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
 * Copyright (C) 2015 Huawei Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License (not later!)
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not,  see <http://www.gnu.org/licenses>
 */
#ifndef __LIBBPF_BPF_H
#define __LIBBPF_BPF_H

#include <linux/bpf.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "libbpf_common.h"

#ifdef __cplusplus
extern "C" {
#endif

struct bpf_create_map_attr {
	const char *name;
	enum bpf_map_type map_type;
	__u32 map_flags;
	__u32 key_size;
	__u32 value_size;
	__u32 max_entries;
	__u32 numa_node;
	__u32 btf_fd;
	__u32 btf_key_type_id;
	__u32 btf_value_type_id;
	__u32 map_ifindex;
	union {
		__u32 inner_map_fd;
		__u32 btf_vmlinux_value_type_id;
	};
};

LIBBPF_API int
bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr);
LIBBPF_API int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
				   int key_size, int value_size,
				   int max_entries, __u32 map_flags, int node);
LIBBPF_API int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
				   int key_size, int value_size,
				   int max_entries, __u32 map_flags);
LIBBPF_API int bpf_create_map(enum bpf_map_type map_type, int key_size,
			      int value_size, int max_entries, __u32 map_flags);
LIBBPF_API int bpf_create_map_in_map_node(enum bpf_map_type map_type,
					  const char *name, int key_size,
					  int inner_map_fd, int max_entries,
					  __u32 map_flags, int node);
LIBBPF_API int bpf_create_map_in_map(enum bpf_map_type map_type,
				     const char *name, int key_size,
				     int inner_map_fd, int max_entries,
				     __u32 map_flags);

struct bpf_load_program_attr {
	enum bpf_prog_type prog_type;
	enum bpf_attach_type expected_attach_type;
	const char *name;
	const struct bpf_insn *insns;
	size_t insns_cnt;
	const char *license;
	union {
		__u32 kern_version;
		__u32 attach_prog_fd;
	};
	union {
		__u32 prog_ifindex;
		__u32 attach_btf_id;
	};
	__u32 prog_btf_fd;
	__u32 func_info_rec_size;
	const void *func_info;
	__u32 func_info_cnt;
	__u32 line_info_rec_size;
	const void *line_info;
	__u32 line_info_cnt;
	__u32 log_level;
	__u32 prog_flags;
};

/* Flags to direct loading requirements */
#define MAPS_RELAX_COMPAT	0x01

/* Recommend log buffer size */
#define BPF_LOG_BUF_SIZE (UINT32_MAX >> 8) /* verifier maximum in kernels <= 5.1 */
LIBBPF_API int
bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
		       char *log_buf, size_t log_buf_sz);
LIBBPF_API int bpf_load_program(enum bpf_prog_type type,
				const struct bpf_insn *insns, size_t insns_cnt,
				const char *license, __u32 kern_version,
				char *log_buf, size_t log_buf_sz);
LIBBPF_API int bpf_verify_program(enum bpf_prog_type type,
				  const struct bpf_insn *insns,
				  size_t insns_cnt, __u32 prog_flags,
				  const char *license, __u32 kern_version,
				  char *log_buf, size_t log_buf_sz,
				  int log_level);

LIBBPF_API int bpf_map_update_elem(int fd, const void *key, const void *value,
				   __u64 flags);

LIBBPF_API int bpf_map_lookup_elem(int fd, const void *key, void *value);
LIBBPF_API int bpf_map_lookup_elem_flags(int fd, const void *key, void *value,
					 __u64 flags);
LIBBPF_API int bpf_map_lookup_and_delete_elem(int fd, const void *key,
					      void *value);
LIBBPF_API int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key,
						    void *value, __u64 flags);
LIBBPF_API int bpf_map_delete_elem(int fd, const void *key);
LIBBPF_API int bpf_map_get_next_key(int fd, const void *key, void *next_key);
LIBBPF_API int bpf_map_freeze(int fd);

struct bpf_map_batch_opts {
	size_t sz; /* size of this struct for forward/backward compatibility */
	__u64 elem_flags;
	__u64 flags;
};
#define bpf_map_batch_opts__last_field flags

LIBBPF_API int bpf_map_delete_batch(int fd, void *keys,
				    __u32 *count,
				    const struct bpf_map_batch_opts *opts);
LIBBPF_API int bpf_map_lookup_batch(int fd, void *in_batch, void *out_batch,
				    void *keys, void *values, __u32 *count,
				    const struct bpf_map_batch_opts *opts);
LIBBPF_API int bpf_map_lookup_and_delete_batch(int fd, void *in_batch,
					void *out_batch, void *keys,
					void *values, __u32 *count,
					const struct bpf_map_batch_opts *opts);
LIBBPF_API int bpf_map_update_batch(int fd, void *keys, void *values,
				    __u32 *count,
				    const struct bpf_map_batch_opts *opts);

LIBBPF_API int bpf_obj_pin(int fd, const char *pathname);
LIBBPF_API int bpf_obj_get(const char *pathname);

struct bpf_prog_attach_opts {
	size_t sz; /* size of this struct for forward/backward compatibility */
	unsigned int flags;
	int replace_prog_fd;
};
#define bpf_prog_attach_opts__last_field replace_prog_fd

LIBBPF_API int bpf_prog_attach(int prog_fd, int attachable_fd,
			       enum bpf_attach_type type, unsigned int flags);
LIBBPF_API int bpf_prog_attach_xattr(int prog_fd, int attachable_fd,
				     enum bpf_attach_type type,
				     const struct bpf_prog_attach_opts *opts);
LIBBPF_API int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd,
				enum bpf_attach_type type);

union bpf_iter_link_info; /* defined in up-to-date linux/bpf.h */
struct bpf_link_create_opts {
	size_t sz; /* size of this struct for forward/backward compatibility */
	__u32 flags;
	union bpf_iter_link_info *iter_info;
	__u32 iter_info_len;
	__u32 target_btf_id;
	union {
		struct {
			__u64 bpf_cookie;
		} perf_event;
	};
	size_t :0;
};
#define bpf_link_create_opts__last_field perf_event

LIBBPF_API int bpf_link_create(int prog_fd, int target_fd,
			       enum bpf_attach_type attach_type,
			       const struct bpf_link_create_opts *opts);

LIBBPF_API int bpf_link_detach(int link_fd);

struct bpf_link_update_opts {
	size_t sz; /* size of this struct for forward/backward compatibility */
	__u32 flags;	   /* extra flags */
	__u32 old_prog_fd; /* expected old program FD */
};
#define bpf_link_update_opts__last_field old_prog_fd

LIBBPF_API int bpf_link_update(int link_fd, int new_prog_fd,
			       const struct bpf_link_update_opts *opts);

LIBBPF_API int bpf_iter_create(int link_fd);

struct bpf_prog_test_run_attr {
	int prog_fd;
	int repeat;
	const void *data_in;
	__u32 data_size_in;
	void *data_out;      /* optional */
	__u32 data_size_out; /* in: max length of data_out
			      * out: length of data_out */
	__u32 retval;        /* out: return code of the BPF program */
	__u32 duration;      /* out: average per repetition in ns */
	const void *ctx_in; /* optional */
	__u32 ctx_size_in;
	void *ctx_out;      /* optional */
	__u32 ctx_size_out; /* in: max length of ctx_out
			     * out: length of cxt_out */
};

LIBBPF_API int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr);

/*
 * bpf_prog_test_run does not check that data_out is large enough. Consider
 * using bpf_prog_test_run_xattr instead.
 */
LIBBPF_API int bpf_prog_test_run(int prog_fd, int repeat, void *data,
				 __u32 size, void *data_out, __u32 *size_out,
				 __u32 *retval, __u32 *duration);
LIBBPF_API int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id);
LIBBPF_API int bpf_map_get_next_id(__u32 start_id, __u32 *next_id);
LIBBPF_API int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id);
LIBBPF_API int bpf_link_get_next_id(__u32 start_id, __u32 *next_id);
LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
LIBBPF_API int bpf_map_get_fd_by_id(__u32 id);
LIBBPF_API int bpf_btf_get_fd_by_id(__u32 id);
LIBBPF_API int bpf_link_get_fd_by_id(__u32 id);
LIBBPF_API int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len);
LIBBPF_API int bpf_prog_query(int target_fd, enum bpf_attach_type type,
			      __u32 query_flags, __u32 *attach_flags,
			      __u32 *prog_ids, __u32 *prog_cnt);
LIBBPF_API int bpf_raw_tracepoint_open(const char *name, int prog_fd);
LIBBPF_API int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf,
			    __u32 log_buf_size, bool do_log);
LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
				 __u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
				 __u64 *probe_offset, __u64 *probe_addr);

enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */
LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type);

struct bpf_prog_bind_opts {
	size_t sz; /* size of this struct for forward/backward compatibility */
	__u32 flags;
};
#define bpf_prog_bind_opts__last_field flags

LIBBPF_API int bpf_prog_bind_map(int prog_fd, int map_fd,
				 const struct bpf_prog_bind_opts *opts);

struct bpf_test_run_opts {
	size_t sz; /* size of this struct for forward/backward compatibility */
	const void *data_in; /* optional */
	void *data_out;      /* optional */
	__u32 data_size_in;
	__u32 data_size_out; /* in: max length of data_out
			      * out: length of data_out
			      */
	const void *ctx_in; /* optional */
	void *ctx_out;      /* optional */
	__u32 ctx_size_in;
	__u32 ctx_size_out; /* in: max length of ctx_out
			     * out: length of cxt_out
			     */
	__u32 retval;        /* out: return code of the BPF program */
	int repeat;
	__u32 duration;      /* out: average per repetition in ns */
	__u32 flags;
	__u32 cpu;
};
#define bpf_test_run_opts__last_field cpu

LIBBPF_API int bpf_prog_test_run_opts(int prog_fd,
				      struct bpf_test_run_opts *opts);

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* __LIBBPF_BPF_H */


================================================
FILE: include/libbpf/bpf_core_read.h
================================================
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __BPF_CORE_READ_H__
#define __BPF_CORE_READ_H__

/*
 * enum bpf_field_info_kind is passed as a second argument into
 * __builtin_preserve_field_info() built-in to get a specific aspect of
 * a field, captured as a first argument. __builtin_preserve_field_info(field,
 * info_kind) returns __u32 integer and produces BTF field relocation, which
 * is understood and processed by libbpf during BPF object loading. See
 * selftests/bpf for examples.
 */
enum bpf_field_info_kind {
	BPF_FIELD_BYTE_OFFSET = 0,	/* field byte offset */
	BPF_FIELD_BYTE_SIZE = 1,
	BPF_FIELD_EXISTS = 2,		/* field existence in target kernel */
	BPF_FIELD_SIGNED = 3,
	BPF_FIELD_LSHIFT_U64 = 4,
	BPF_FIELD_RSHIFT_U64 = 5,
};

/* second argument to __builtin_btf_type_id() built-in */
enum bpf_type_id_kind {
	BPF_TYPE_ID_LOCAL = 0,		/* BTF type ID in local program */
	BPF_TYPE_ID_TARGET = 1,		/* BTF type ID in target kernel */
};

/* second argument to __builtin_preserve_type_info() built-in */
enum bpf_type_info_kind {
	BPF_TYPE_EXISTS = 0,		/* type existence in target kernel */
	BPF_TYPE_SIZE = 1,		/* type size in target kernel */
};

/* second argument to __builtin_preserve_enum_value() built-in */
enum bpf_enum_value_kind {
	BPF_ENUMVAL_EXISTS = 0,		/* enum value existence in kernel */
	BPF_ENUMVAL_VALUE = 1,		/* enum value value relocation */
};

#define __CORE_RELO(src, field, info)					      \
	__builtin_preserve_field_info((src)->field, BPF_FIELD_##info)

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define __CORE_BITFIELD_PROBE_READ(dst, src, fld)			      \
	bpf_probe_read_kernel(						      \
			(void *)dst,				      \
			__CORE_RELO(src, fld, BYTE_SIZE),		      \
			(const void *)src + __CORE_RELO(src, fld, BYTE_OFFSET))
#else
/* semantics of LSHIFT_64 assumes loading values into low-ordered bytes, so
 * for big-endian we need to adjust destination pointer accordingly, based on
 * field byte size
 */
#define __CORE_BITFIELD_PROBE_READ(dst, src, fld)			      \
	bpf_probe_read_kernel(						      \
			(void *)dst + (8 - __CORE_RELO(src, fld, BYTE_SIZE)), \
			__CORE_RELO(src, fld, BYTE_SIZE),		      \
			(const void *)src + __CORE_RELO(src, fld, BYTE_OFFSET))
#endif

/*
 * Extract bitfield, identified by s->field, and return its value as u64.
 * All this is done in relocatable manner, so bitfield changes such as
 * signedness, bit size, offset changes, this will be handled automatically.
 * This version of macro is using bpf_probe_read_kernel() to read underlying
 * integer storage. Macro functions as an expression and its return type is
 * bpf_probe_read_kernel()'s return value: 0, on success, <0 on error.
 */
#define BPF_CORE_READ_BITFIELD_PROBED(s, field) ({			      \
	unsigned long long val = 0;					      \
									      \
	__CORE_BITFIELD_PROBE_READ(&val, s, field);			      \
	val <<= __CORE_RELO(s, field, LSHIFT_U64);			      \
	if (__CORE_RELO(s, field, SIGNED))				      \
		val = ((long long)val) >> __CORE_RELO(s, field, RSHIFT_U64);  \
	else								      \
		val = val >> __CORE_RELO(s, field, RSHIFT_U64);		      \
	val;								      \
})

/*
 * Extract bitfield, identified by s->field, and return its value as u64.
 * This version of macro is using direct memory reads and should be used from
 * BPF program types that support such functionality (e.g., typed raw
 * tracepoints).
 */
#define BPF_CORE_READ_BITFIELD(s, field) ({				      \
	const void *p = (const void *)s + __CORE_RELO(s, field, BYTE_OFFSET); \
	unsigned long long val;						      \
									      \
	/* This is a so-called barrier_var() operation that makes specified   \
	 * variable "a black box" for optimizing compiler.		      \
	 * It forces compiler to perform BYTE_OFFSET relocation on p and use  \
	 * its calculated value in the switch below, instead of applying      \
	 * the same relocation 4 times for each individual memory load.       \
	 */								      \
	asm volatile("" : "=r"(p) : "0"(p));				      \
									      \
	switch (__CORE_RELO(s, field, BYTE_SIZE)) {			      \
	case 1: val = *(const unsigned char *)p; break;			      \
	case 2: val = *(const unsigned short *)p; break;		      \
	case 4: val = *(const unsigned int *)p; break;			      \
	case 8: val = *(const unsigned long long *)p; break;		      \
	}								      \
	val <<= __CORE_RELO(s, field, LSHIFT_U64);			      \
	if (__CORE_RELO(s, field, SIGNED))				      \
		val = ((long long)val) >> __CORE_RELO(s, field, RSHIFT_U64);  \
	else								      \
		val = val >> __CORE_RELO(s, field, RSHIFT_U64);		      \
	val;								      \
})

/*
 * Convenience macro to check that field actually exists in target kernel's.
 * Returns:
 *    1, if matching field is present in target kernel;
 *    0, if no matching field found.
 */
#define bpf_core_field_exists(field)					    \
	__builtin_preserve_field_info(field, BPF_FIELD_EXISTS)

/*
 * Convenience macro to get the byte size of a field. Works for integers,
 * struct/unions, pointers, arrays, and enums.
 */
#define bpf_core_field_size(field)					    \
	__builtin_preserve_field_info(field, BPF_FIELD_BYTE_SIZE)

/*
 * Convenience macro to get BTF type ID of a specified type, using a local BTF
 * information. Return 32-bit unsigned integer with type ID from program's own
 * BTF. Always succeeds.
 */
#define bpf_core_type_id_local(type)					    \
	__builtin_btf_type_id(*(typeof(type) *)0, BPF_TYPE_ID_LOCAL)

/*
 * Convenience macro to get BTF type ID of a target kernel's type that matches
 * specified local type.
 * Returns:
 *    - valid 32-bit unsigned type ID in kernel BTF;
 *    - 0, if no matching type was found in a target kernel BTF.
 */
#define bpf_core_type_id_kernel(type)					    \
	__builtin_btf_type_id(*(typeof(type) *)0, BPF_TYPE_ID_TARGET)

/*
 * Convenience macro to check that provided named type
 * (struct/union/enum/typedef) exists in a target kernel.
 * Returns:
 *    1, if such type is present in target kernel's BTF;
 *    0, if no matching type is found.
 */
#define bpf_core_type_exists(type)					    \
	__builtin_preserve_type_info(*(typeof(type) *)0, BPF_TYPE_EXISTS)

/*
 * Convenience macro to get the byte size of a provided named type
 * (struct/union/enum/typedef) in a target kernel.
 * Returns:
 *    >= 0 size (in bytes), if type is present in target kernel's BTF;
 *    0, if no matching type is found.
 */
#define bpf_core_type_size(type)					    \
	__builtin_preserve_type_info(*(typeof(type) *)0, BPF_TYPE_SIZE)

/*
 * Convenience macro to check that provided enumerator value is defined in
 * a target kernel.
 * Returns:
 *    1, if specified enum type and its enumerator value are present in target
 *    kernel's BTF;
 *    0, if no matching enum and/or enum value within that enum is found.
 */
#define bpf_core_enum_value_exists(enum_type, enum_value)		    \
	__builtin_preserve_enum_value(*(typeof(enum_type) *)enum_value, BPF_ENUMVAL_EXISTS)

/*
 * Convenience macro to get the integer value of an enumerator value in
 * a target kernel.
 * Returns:
 *    64-bit value, if specified enum type and its enumerator value are
 *    present in target kernel's BTF;
 *    0, if no matching enum and/or enum value within that enum is found.
 */
#define bpf_core_enum_value(enum_type, enum_value)			    \
	__builtin_preserve_enum_value(*(typeof(enum_type) *)enum_value, BPF_ENUMVAL_VALUE)

/*
 * bpf_core_read() abstracts away bpf_probe_read_kernel() call and captures
 * offset relocation for source address using __builtin_preserve_access_index()
 * built-in, provided by Clang.
 *
 * __builtin_preserve_access_index() takes as an argument an expression of
 * taking an address of a field within struct/union. It makes compiler emit
 * a relocation, which records BTF type ID describing root struct/union and an
 * accessor string which describes exact embedded field that was used to take
 * an address. See detailed description of this relocation format and
 * semantics in comments to struct bpf_field_reloc in libbpf_internal.h.
 *
 * This relocation allows libbpf to adjust BPF instruction to use correct
 * actual field offset, based on target kernel BTF type that matches original
 * (local) BTF, used to record relocation.
 */
#define bpf_core_read(dst, sz, src)					    \
	bpf_probe_read_kernel(dst, sz, (const void *)__builtin_preserve_access_index(src))

/* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. */
#define bpf_core_read_user(dst, sz, src)				    \
	bpf_probe_read_user(dst, sz, (const void *)__builtin_preserve_access_index(src))
/*
 * bpf_core_read_str() is a thin wrapper around bpf_probe_read_str()
 * additionally emitting BPF CO-RE field relocation for specified source
 * argument.
 */
#define bpf_core_read_str(dst, sz, src)					    \
	bpf_probe_read_kernel_str(dst, sz, (const void *)__builtin_preserve_access_index(src))

/* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. */
#define bpf_core_read_user_str(dst, sz, src)				    \
	bpf_probe_read_user_str(dst, sz, (const void *)__builtin_preserve_access_index(src))

#define ___concat(a, b) a ## b
#define ___apply(fn, n) ___concat(fn, n)
#define ___nth(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, __11, N, ...) N

/*
 * return number of provided arguments; used for switch-based variadic macro
 * definitions (see ___last, ___arrow, etc below)
 */
#define ___narg(...) ___nth(_, ##__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
/*
 * return 0 if no arguments are passed, N - otherwise; used for
 * recursively-defined macros to specify termination (0) case, and generic
 * (N) case (e.g., ___read_ptrs, ___core_read)
 */
#define ___empty(...) ___nth(_, ##__VA_ARGS__, N, N, N, N, N, N, N, N, N, N, 0)

#define ___last1(x) x
#define ___last2(a, x) x
#define ___last3(a, b, x) x
#define ___last4(a, b, c, x) x
#define ___last5(a, b, c, d, x) x
#define ___last6(a, b, c, d, e, x) x
#define ___last7(a, b, c, d, e, f, x) x
#define ___last8(a, b, c, d, e, f, g, x) x
#define ___last9(a, b, c, d, e, f, g, h, x) x
#define ___last10(a, b, c, d, e, f, g, h, i, x) x
#define ___last(...) ___apply(___last, ___narg(__VA_ARGS__))(__VA_ARGS__)

#define ___nolast2(a, _) a
#define ___nolast3(a, b, _) a, b
#define ___nolast4(a, b, c, _) a, b, c
#define ___nolast5(a, b, c, d, _) a, b, c, d
#define ___nolast6(a, b, c, d, e, _) a, b, c, d, e
#define ___nolast7(a, b, c, d, e, f, _) a, b, c, d, e, f
#define ___nolast8(a, b, c, d, e, f, g, _) a, b, c, d, e, f, g
#define ___nolast9(a, b, c, d, e, f, g, h, _) a, b, c, d, e, f, g, h
#define ___nolast10(a, b, c, d, e, f, g, h, i, _) a, b, c, d, e, f, g, h, i
#define ___nolast(...) ___apply(___nolast, ___narg(__VA_ARGS__))(__VA_ARGS__)

#define ___arrow1(a) a
#define ___arrow2(a, b) a->b
#define ___arrow3(a, b, c) a->b->c
#define ___arrow4(a, b, c, d) a->b->c->d
#define ___arrow5(a, b, c, d, e) a->b->c->d->e
#define ___arrow6(a, b, c, d, e, f) a->b->c->d->e->f
#define ___arrow7(a, b, c, d, e, f, g) a->b->c->d->e->f->g
#define ___arrow8(a, b, c, d, e, f, g, h) a->b->c->d->e->f->g->h
#define ___arrow9(a, b, c, d, e, f, g, h, i) a->b->c->d->e->f->g->h->i
#define ___arrow10(a, b, c, d, e, f, g, h, i, j) a->b->c->d->e->f->g->h->i->j
#define ___arrow(...) ___apply(___arrow, ___narg(__VA_ARGS__))(__VA_ARGS__)

#define ___type(...) typeof(___arrow(__VA_ARGS__))

#define ___read(read_fn, dst, src_type, src, accessor)			    \
	read_fn((void *)(dst), sizeof(*(dst)), &((src_type)(src))->accessor)

/* "recursively" read a sequence of inner pointers using local __t var */
#define ___rd_first(fn, src, a) ___read(fn, &__t, ___type(src), src, a);
#define ___rd_last(fn, ...)						    \
	___read(fn, &__t, ___type(___nolast(__VA_ARGS__)), __t, ___last(__VA_ARGS__));
#define ___rd_p1(fn, ...) const void *__t; ___rd_first(fn, __VA_ARGS__)
#define ___rd_p2(fn, ...) ___rd_p1(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
#define ___rd_p3(fn, ...) ___rd_p2(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
#define ___rd_p4(fn, ...) ___rd_p3(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
#define ___rd_p5(fn, ...) ___rd_p4(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
#define ___rd_p6(fn, ...) ___rd_p5(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
#define ___rd_p7(fn, ...) ___rd_p6(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
#define ___rd_p8(fn, ...) ___rd_p7(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
#define ___rd_p9(fn, ...) ___rd_p8(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__)
#define ___read_ptrs(fn, src, ...)					    \
	___apply(___rd_p, ___narg(__VA_ARGS__))(fn, src, __VA_ARGS__)

#define ___core_read0(fn, fn_ptr, dst, src, a)				    \
	___read(fn, dst, ___type(src), src, a);
#define ___core_readN(fn, fn_ptr, dst, src, ...)			    \
	___read_ptrs(fn_ptr, src, ___nolast(__VA_ARGS__))		    \
	___read(fn, dst, ___type(src, ___nolast(__VA_ARGS__)), __t,	    \
		___last(__VA_ARGS__));
#define ___core_read(fn, fn_ptr, dst, src, a, ...)			    \
	___apply(___core_read, ___empty(__VA_ARGS__))(fn, fn_ptr, dst,	    \
						      src, a, ##__VA_ARGS__)

/*
 * BPF_CORE_READ_INTO() is a more performance-conscious variant of
 * BPF_CORE_READ(), in which final field is read into user-provided storage.
 * See BPF_CORE_READ() below for more details on general usage.
 */
#define BPF_CORE_READ_INTO(dst, src, a, ...) ({				    \
	___core_read(bpf_core_read, bpf_core_read,			    \
		     dst, (src), a, ##__VA_ARGS__)			    \
})

/*
 * Variant of BPF_CORE_READ_INTO() for reading from user-space memory.
 *
 * NOTE: see comments for BPF_CORE_READ_USER() about the proper types use.
 */
#define BPF_CORE_READ_USER_INTO(dst, src, a, ...) ({			    \
	___core_read(bpf_core_read_user, bpf_core_read_user,		    \
		     dst, (src), a, ##__VA_ARGS__)			    \
})

/* Non-CO-RE variant of BPF_CORE_READ_INTO() */
#define BPF_PROBE_READ_INTO(dst, src, a, ...) ({			    \
	___core_read(bpf_probe_read, bpf_probe_read,			    \
		     dst, (src), a, ##__VA_ARGS__)			    \
})

/* Non-CO-RE variant of BPF_CORE_READ_USER_INTO().
 *
 * As no CO-RE relocations are emitted, source types can be arbitrary and are
 * not restricted to kernel types only.
 */
#define BPF_PROBE_READ_USER_INTO(dst, src, a, ...) ({			    \
	___core_read(bpf_probe_read_user, bpf_probe_read_user,		    \
		     dst, (src), a, ##__VA_ARGS__)			    \
})

/*
 * BPF_CORE_READ_STR_INTO() does same "pointer chasing" as
 * BPF_CORE_READ() for intermediate pointers, but then executes (and returns
 * corresponding error code) bpf_core_read_str() for final string read.
 */
#define BPF_CORE_READ_STR_INTO(dst, src, a, ...) ({			    \
	___core_read(bpf_core_read_str, bpf_core_read,			    \
		     dst, (src), a, ##__VA_ARGS__)			    \
})

/*
 * Variant of BPF_CORE_READ_STR_INTO() for reading from user-space memory.
 *
 * NOTE: see comments for BPF_CORE_READ_USER() about the proper types use.
 */
#define BPF_CORE_READ_USER_STR_INTO(dst, src, a, ...) ({		    \
	___core_read(bpf_core_read_user_str, bpf_core_read_user,	    \
		     dst, (src), a, ##__VA_ARGS__)			    \
})

/* Non-CO-RE variant of BPF_CORE_READ_STR_INTO() */
#define BPF_PROBE_READ_STR_INTO(dst, src, a, ...) ({			    \
	___core_read(bpf_probe_read_str, bpf_probe_read,		    \
		     dst, (src), a, ##__VA_ARGS__)			    \
})

/*
 * Non-CO-RE variant of BPF_CORE_READ_USER_STR_INTO().
 *
 * As no CO-RE relocations are emitted, source types can be arbitrary and are
 * not restricted to kernel types only.
 */
#define BPF_PROBE_READ_USER_STR_INTO(dst, src, a, ...) ({		    \
	___core_read(bpf_probe_read_user_str, bpf_probe_read_user,	    \
		     dst, (src), a, ##__VA_ARGS__)			    \
})

/*
 * BPF_CORE_READ() is used to simplify BPF CO-RE relocatable read, especially
 * when there are few pointer chasing steps.
 * E.g., what in non-BPF world (or in BPF w/ BCC) would be something like:
 *	int x = s->a.b.c->d.e->f->g;
 * can be succinctly achieved using BPF_CORE_READ as:
 *	int x = BPF_CORE_READ(s, a.b.c, d.e, f, g);
 *
 * BPF_CORE_READ will decompose above statement into 4 bpf_core_read (BPF
 * CO-RE relocatable bpf_probe_read_kernel() wrapper) calls, logically
 * equivalent to:
 * 1. const void *__t = s->a.b.c;
 * 2. __t = __t->d.e;
 * 3. __t = __t->f;
 * 4. return __t->g;
 *
 * Equivalence is logical, because there is a heavy type casting/preservation
 * involved, as well as all the reads are happening through
 * bpf_probe_read_kernel() calls using __builtin_preserve_access_index() to
 * emit CO-RE relocations.
 *
 * N.B. Only up to 9 "field accessors" are supported, which should be more
 * than enough for any practical purpose.
 */
#define BPF_CORE_READ(src, a, ...) ({					    \
	___type((src), a, ##__VA_ARGS__) __r;				    \
	BPF_CORE_READ_INTO(&__r, (src), a, ##__VA_ARGS__);		    \
	__r;								    \
})

/*
 * Variant of BPF_CORE_READ() for reading from user-space memory.
 *
 * NOTE: all the source types involved are still *kernel types* and need to
 * exist in kernel (or kernel module) BTF, otherwise CO-RE relocation will
 * fail. Custom user types are not relocatable with CO-RE.
 * The typical situation in which BPF_CORE_READ_USER() might be used is to
 * read kernel UAPI types from the user-space memory passed in as a syscall
 * input argument.
 */
#define BPF_CORE_READ_USER(src, a, ...) ({				    \
	___type((src), a, ##__VA_ARGS__) __r;				    \
	BPF_CORE_READ_USER_INTO(&__r, (src), a, ##__VA_ARGS__);		    \
	__r;								    \
})

/* Non-CO-RE variant of BPF_CORE_READ() */
#define BPF_PROBE_READ(src, a, ...) ({					    \
	___type((src), a, ##__VA_ARGS__) __r;				    \
	BPF_PROBE_READ_INTO(&__r, (src), a, ##__VA_ARGS__);		    \
	__r;								    \
})

/*
 * Non-CO-RE variant of BPF_CORE_READ_USER().
 *
 * As no CO-RE relocations are emitted, source types can be arbitrary and are
 * not restricted to kernel types only.
 */
#define BPF_PROBE_READ_USER(src, a, ...) ({				    \
	___type((src), a, ##__VA_ARGS__) __r;				    \
	BPF_PROBE_READ_USER_INTO(&__r, (src), a, ##__VA_ARGS__);	    \
	__r;								    \
})

#endif



================================================
FILE: include/libbpf/bpf_endian.h
================================================
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __BPF_ENDIAN__
#define __BPF_ENDIAN__

/*
 * Isolate byte #n and put it into byte #m, for __u##b type.
 * E.g., moving byte #6 (nnnnnnnn) into byte #1 (mmmmmmmm) for __u64:
 * 1) xxxxxxxx nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx
 * 2) nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 00000000
 * 3) 00000000 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn
 * 4) 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 00000000
 */
#define ___bpf_mvb(x, b, n, m) ((__u##b)(x) << (b-(n+1)*8) >> (b-8) << (m*8))

#define ___bpf_swab16(x) ((__u16)(			\
			  ___bpf_mvb(x, 16, 0, 1) |	\
			  ___bpf_mvb(x, 16, 1, 0)))

#define ___bpf_swab32(x) ((__u32)(			\
			  ___bpf_mvb(x, 32, 0, 3) |	\
			  ___bpf_mvb(x, 32, 1, 2) |	\
			  ___bpf_mvb(x, 32, 2, 1) |	\
			  ___bpf_mvb(x, 32, 3, 0)))

#define ___bpf_swab64(x) ((__u64)(			\
			  ___bpf_mvb(x, 64, 0, 7) |	\
			  ___bpf_mvb(x, 64, 1, 6) |	\
			  ___bpf_mvb(x, 64, 2, 5) |	\
			  ___bpf_mvb(x, 64, 3, 4) |	\
			  ___bpf_mvb(x, 64, 4, 3) |	\
			  ___bpf_mvb(x, 64, 5, 2) |	\
			  ___bpf_mvb(x, 64, 6, 1) |	\
			  ___bpf_mvb(x, 64, 7, 0)))

/* LLVM's BPF target selects the endianness of the CPU
 * it compiles on, or the user specifies (bpfel/bpfeb),
 * respectively. The used __BYTE_ORDER__ is defined by
 * the compiler, we cannot rely on __BYTE_ORDER from
 * libc headers, since it doesn't reflect the actual
 * requested byte order.
 *
 * Note, LLVM's BPF target has different __builtin_bswapX()
 * semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
 * in bpfel and bpfeb case, which means below, that we map
 * to cpu_to_be16(). We could use it unconditionally in BPF
 * case, but better not rely on it, so that this header here
 * can be used from application and BPF program side, which
 * use different targets.
 */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define __bpf_ntohs(x)			__builtin_bswap16(x)
# define __bpf_htons(x)			__builtin_bswap16(x)
# define __bpf_constant_ntohs(x)	___bpf_swab16(x)
# define __bpf_constant_htons(x)	___bpf_swab16(x)
# define __bpf_ntohl(x)			__builtin_bswap32(x)
# define __bpf_htonl(x)			__builtin_bswap32(x)
# define __bpf_constant_ntohl(x)	___bpf_swab32(x)
# define __bpf_constant_htonl(x)	___bpf_swab32(x)
# define __bpf_be64_to_cpu(x)		__builtin_bswap64(x)
# define __bpf_cpu_to_be64(x)		__builtin_bswap64(x)
# define __bpf_constant_be64_to_cpu(x)	___bpf_swab64(x)
# define __bpf_constant_cpu_to_be64(x)	___bpf_swab64(x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define __bpf_ntohs(x)			(x)
# define __bpf_htons(x)			(x)
# define __bpf_constant_ntohs(x)	(x)
# define __bpf_constant_htons(x)	(x)
# define __bpf_ntohl(x)			(x)
# define __bpf_htonl(x)			(x)
# define __bpf_constant_ntohl(x)	(x)
# define __bpf_constant_htonl(x)	(x)
# define __bpf_be64_to_cpu(x)		(x)
# define __bpf_cpu_to_be64(x)		(x)
# define __bpf_constant_be64_to_cpu(x)  (x)
# define __bpf_constant_cpu_to_be64(x)  (x)
#else
# error "Fix your compiler's __BYTE_ORDER__?!"
#endif

#define bpf_htons(x)				\
	(__builtin_constant_p(x) ?		\
	 __bpf_constant_htons(x) : __bpf_htons(x))
#define bpf_ntohs(x)				\
	(__builtin_constant_p(x) ?		\
	 __bpf_constant_ntohs(x) : __bpf_ntohs(x))
#define bpf_htonl(x)				\
	(__builtin_constant_p(x) ?		\
	 __bpf_constant_htonl(x) : __bpf_htonl(x))
#define bpf_ntohl(x)				\
	(__builtin_constant_p(x) ?		\
	 __bpf_constant_ntohl(x) : __bpf_ntohl(x))
#define bpf_cpu_to_be64(x)			\
	(__builtin_constant_p(x) ?		\
	 __bpf_constant_cpu_to_be64(x) : __bpf_cpu_to_be64(x))
#define bpf_be64_to_cpu(x)			\
	(__builtin_constant_p(x) ?		\
	 __bpf_constant_be64_to_cpu(x) : __bpf_be64_to_cpu(x))

#endif /* __BPF_ENDIAN__ */


================================================
FILE: include/libbpf/bpf_helper_defs.h
================================================
/* This is auto-generated file. See bpf_doc.py for details. */

/* Forward declarations of BPF structs */
struct bpf_fib_lookup;
struct bpf_sk_lookup;
struct bpf_perf_event_data;
struct bpf_perf_event_value;
struct bpf_pidns_info;
struct bpf_redir_neigh;
struct bpf_sock;
struct bpf_sock_addr;
struct bpf_sock_ops;
struct bpf_sock_tuple;
struct bpf_spin_lock;
struct bpf_sysctl;
struct bpf_tcp_sock;
struct bpf_tunnel_key;
struct bpf_xfrm_state;
struct linux_binprm;
struct pt_regs;
struct sk_reuseport_md;
struct sockaddr;
struct tcphdr;
struct seq_file;
struct tcp6_sock;
struct tcp_sock;
struct tcp_timewait_sock;
struct tcp_request_sock;
struct udp6_sock;
struct task_struct;
struct __sk_buff;
struct sk_msg_md;
struct xdp_md;
struct path;
struct btf_ptr;
struct inode;
struct socket;
struct file;
struct bpf_timer;

/*
 * bpf_map_lookup_elem
 *
 * 	Perform a lookup in *map* for an entry associated to *key*.
 *
 * Returns
 * 	Map value associated to *key*, or **NULL** if no entry was
 * 	found.
 */
static void *(*bpf_map_lookup_elem)(void *map, const void *key) = (void *) 1;

/*
 * bpf_map_update_elem
 *
 * 	Add or update the value of the entry associated to *key* in
 * 	*map* with *value*. *flags* is one of:
 *
 * 	**BPF_NOEXIST**
 * 		The entry for *key* must not exist in the map.
 * 	**BPF_EXIST**
 * 		The entry for *key* must already exist in the map.
 * 	**BPF_ANY**
 * 		No condition on the existence of the entry for *key*.
 *
 * 	Flag value **BPF_NOEXIST** cannot be used for maps of types
 * 	**BPF_MAP_TYPE_ARRAY** or **BPF_MAP_TYPE_PERCPU_ARRAY**  (all
 * 	elements always exist), the helper would return an error.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_map_update_elem)(void *map, const void *key, const void *value, __u64 flags) = (void *) 2;

/*
 * bpf_map_delete_elem
 *
 * 	Delete entry with *key* from *map*.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_map_delete_elem)(void *map, const void *key) = (void *) 3;

/*
 * bpf_probe_read
 *
 * 	For tracing programs, safely attempt to read *size* bytes from
 * 	kernel space address *unsafe_ptr* and store the data in *dst*.
 *
 * 	Generally, use **bpf_probe_read_user**\ () or
 * 	**bpf_probe_read_kernel**\ () instead.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_probe_read)(void *dst, __u32 size, const void *unsafe_ptr) = (void *) 4;

/*
 * bpf_ktime_get_ns
 *
 * 	Return the time elapsed since system boot, in nanoseconds.
 * 	Does not include time the system was suspended.
 * 	See: **clock_gettime**\ (**CLOCK_MONOTONIC**)
 *
 * Returns
 * 	Current *ktime*.
 */
static __u64 (*bpf_ktime_get_ns)(void) = (void *) 5;

/*
 * bpf_trace_printk
 *
 * 	This helper is a "printk()-like" facility for debugging. It
 * 	prints a message defined by format *fmt* (of size *fmt_size*)
 * 	to file *\/sys/kernel/debug/tracing/trace* from DebugFS, if
 * 	available. It can take up to three additional **u64**
 * 	arguments (as an eBPF helpers, the total number of arguments is
 * 	limited to five).
 *
 * 	Each time the helper is called, it appends a line to the trace.
 * 	Lines are discarded while *\/sys/kernel/debug/tracing/trace* is
 * 	open, use *\/sys/kernel/debug/tracing/trace_pipe* to avoid this.
 * 	The format of the trace is customizable, and the exact output
 * 	one will get depends on the options set in
 * 	*\/sys/kernel/debug/tracing/trace_options* (see also the
 * 	*README* file under the same directory). However, it usually
 * 	defaults to something like:
 *
 * 	::
 *
 * 		telnet-470   [001] .N.. 419421.045894: 0x00000001: <formatted msg>
 *
 * 	In the above:
 *
 * 		* ``telnet`` is the name of the current task.
 * 		* ``470`` is the PID of the current task.
 * 		* ``001`` is the CPU number on which the task is
 * 		  running.
 * 		* In ``.N..``, each character refers to a set of
 * 		  options (whether irqs are enabled, scheduling
 * 		  options, whether hard/softirqs are running, level of
 * 		  preempt_disabled respectively). **N** means that
 * 		  **TIF_NEED_RESCHED** and **PREEMPT_NEED_RESCHED**
 * 		  are set.
 * 		* ``419421.045894`` is a timestamp.
 * 		* ``0x00000001`` is a fake value used by BPF for the
 * 		  instruction pointer register.
 * 		* ``<formatted msg>`` is the message formatted with
 * 		  *fmt*.
 *
 * 	The conversion specifiers supported by *fmt* are similar, but
 * 	more limited than for printk(). They are **%d**, **%i**,
 * 	**%u**, **%x**, **%ld**, **%li**, **%lu**, **%lx**, **%lld**,
 * 	**%lli**, **%llu**, **%llx**, **%p**, **%s**. No modifier (size
 * 	of field, padding with zeroes, etc.) is available, and the
 * 	helper will return **-EINVAL** (but print nothing) if it
 * 	encounters an unknown specifier.
 *
 * 	Also, note that **bpf_trace_printk**\ () is slow, and should
 * 	only be used for debugging purposes. For this reason, a notice
 * 	block (spanning several lines) is printed to kernel logs and
 * 	states that the helper should not be used "for production use"
 * 	the first time this helper is used (or more precisely, when
 * 	**trace_printk**\ () buffers are allocated). For passing values
 * 	to user space, perf events should be preferred.
 *
 * Returns
 * 	The number of bytes written to the buffer, or a negative error
 * 	in case of failure.
 */
static long (*bpf_trace_printk)(const char *fmt, __u32 fmt_size, ...) = (void *) 6;

/*
 * bpf_get_prandom_u32
 *
 * 	Get a pseudo-random number.
 *
 * 	From a security point of view, this helper uses its own
 * 	pseudo-random internal state, and cannot be used to infer the
 * 	seed of other random functions in the kernel. However, it is
 * 	essential to note that the generator used by the helper is not
 * 	cryptographically secure.
 *
 * Returns
 * 	A random 32-bit unsigned value.
 */
static __u32 (*bpf_get_prandom_u32)(void) = (void *) 7;

/*
 * bpf_get_smp_processor_id
 *
 * 	Get the SMP (symmetric multiprocessing) processor id. Note that
 * 	all programs run with preemption disabled, which means that the
 * 	SMP processor id is stable during all the execution of the
 * 	program.
 *
 * Returns
 * 	The SMP id of the processor running the program.
 */
static __u32 (*bpf_get_smp_processor_id)(void) = (void *) 8;

/*
 * bpf_skb_store_bytes
 *
 * 	Store *len* bytes from address *from* into the packet
 * 	associated to *skb*, at *offset*. *flags* are a combination of
 * 	**BPF_F_RECOMPUTE_CSUM** (automatically recompute the
 * 	checksum for the packet after storing the bytes) and
 * 	**BPF_F_INVALIDATE_HASH** (set *skb*\ **->hash**, *skb*\
 * 	**->swhash** and *skb*\ **->l4hash** to 0).
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_store_bytes)(struct __sk_buff *skb, __u32 offset, const void *from, __u32 len, __u64 flags) = (void *) 9;

/*
 * bpf_l3_csum_replace
 *
 * 	Recompute the layer 3 (e.g. IP) checksum for the packet
 * 	associated to *skb*. Computation is incremental, so the helper
 * 	must know the former value of the header field that was
 * 	modified (*from*), the new value of this field (*to*), and the
 * 	number of bytes (2 or 4) for this field, stored in *size*.
 * 	Alternatively, it is possible to store the difference between
 * 	the previous and the new values of the header field in *to*, by
 * 	setting *from* and *size* to 0. For both methods, *offset*
 * 	indicates the location of the IP checksum within the packet.
 *
 * 	This helper works in combination with **bpf_csum_diff**\ (),
 * 	which does not update the checksum in-place, but offers more
 * 	flexibility and can handle sizes larger than 2 or 4 for the
 * 	checksum to update.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_l3_csum_replace)(struct __sk_buff *skb, __u32 offset, __u64 from, __u64 to, __u64 size) = (void *) 10;

/*
 * bpf_l4_csum_replace
 *
 * 	Recompute the layer 4 (e.g. TCP, UDP or ICMP) checksum for the
 * 	packet associated to *skb*. Computation is incremental, so the
 * 	helper must know the former value of the header field that was
 * 	modified (*from*), the new value of this field (*to*), and the
 * 	number of bytes (2 or 4) for this field, stored on the lowest
 * 	four bits of *flags*. Alternatively, it is possible to store
 * 	the difference between the previous and the new values of the
 * 	header field in *to*, by setting *from* and the four lowest
 * 	bits of *flags* to 0. For both methods, *offset* indicates the
 * 	location of the IP checksum within the packet. In addition to
 * 	the size of the field, *flags* can be added (bitwise OR) actual
 * 	flags. With **BPF_F_MARK_MANGLED_0**, a null checksum is left
 * 	untouched (unless **BPF_F_MARK_ENFORCE** is added as well), and
 * 	for updates resulting in a null checksum the value is set to
 * 	**CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates
 * 	the checksum is to be computed against a pseudo-header.
 *
 * 	This helper works in combination with **bpf_csum_diff**\ (),
 * 	which does not update the checksum in-place, but offers more
 * 	flexibility and can handle sizes larger than 2 or 4 for the
 * 	checksum to update.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_l4_csum_replace)(struct __sk_buff *skb, __u32 offset, __u64 from, __u64 to, __u64 flags) = (void *) 11;

/*
 * bpf_tail_call
 *
 * 	This special helper is used to trigger a "tail call", or in
 * 	other words, to jump into another eBPF program. The same stack
 * 	frame is used (but values on stack and in registers for the
 * 	caller are not accessible to the callee). This mechanism allows
 * 	for program chaining, either for raising the maximum number of
 * 	available eBPF instructions, or to execute given programs in
 * 	conditional blocks. For security reasons, there is an upper
 * 	limit to the number of successive tail calls that can be
 * 	performed.
 *
 * 	Upon call of this helper, the program attempts to jump into a
 * 	program referenced at index *index* in *prog_array_map*, a
 * 	special map of type **BPF_MAP_TYPE_PROG_ARRAY**, and passes
 * 	*ctx*, a pointer to the context.
 *
 * 	If the call succeeds, the kernel immediately runs the first
 * 	instruction of the new program. This is not a function call,
 * 	and it never returns to the previous program. If the call
 * 	fails, then the helper has no effect, and the caller continues
 * 	to run its subsequent instructions. A call can fail if the
 * 	destination program for the jump does not exist (i.e. *index*
 * 	is superior to the number of entries in *prog_array_map*), or
 * 	if the maximum number of tail calls has been reached for this
 * 	chain of programs. This limit is defined in the kernel by the
 * 	macro **MAX_TAIL_CALL_CNT** (not accessible to user space),
 * 	which is currently set to 32.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_tail_call)(void *ctx, void *prog_array_map, __u32 index) = (void *) 12;

/*
 * bpf_clone_redirect
 *
 * 	Clone and redirect the packet associated to *skb* to another
 * 	net device of index *ifindex*. Both ingress and egress
 * 	interfaces can be used for redirection. The **BPF_F_INGRESS**
 * 	value in *flags* is used to make the distinction (ingress path
 * 	is selected if the flag is present, egress path otherwise).
 * 	This is the only flag supported for now.
 *
 * 	In comparison with **bpf_redirect**\ () helper,
 * 	**bpf_clone_redirect**\ () has the associated cost of
 * 	duplicating the packet buffer, but this can be executed out of
 * 	the eBPF program. Conversely, **bpf_redirect**\ () is more
 * 	efficient, but it is handled through an action code where the
 * 	redirection happens only after the eBPF program has returned.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_clone_redirect)(struct __sk_buff *skb, __u32 ifindex, __u64 flags) = (void *) 13;

/*
 * bpf_get_current_pid_tgid
 *
 *
 * Returns
 * 	A 64-bit integer containing the current tgid and pid, and
 * 	created as such:
 * 	*current_task*\ **->tgid << 32 \|**
 * 	*current_task*\ **->pid**.
 */
static __u64 (*bpf_get_current_pid_tgid)(void) = (void *) 14;

/*
 * bpf_get_current_uid_gid
 *
 *
 * Returns
 * 	A 64-bit integer containing the current GID and UID, and
 * 	created as such: *current_gid* **<< 32 \|** *current_uid*.
 */
static __u64 (*bpf_get_current_uid_gid)(void) = (void *) 15;

/*
 * bpf_get_current_comm
 *
 * 	Copy the **comm** attribute of the current task into *buf* of
 * 	*size_of_buf*. The **comm** attribute contains the name of
 * 	the executable (excluding the path) for the current task. The
 * 	*size_of_buf* must be strictly positive. On success, the
 * 	helper makes sure that the *buf* is NUL-terminated. On failure,
 * 	it is filled with zeroes.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_get_current_comm)(void *buf, __u32 size_of_buf) = (void *) 16;

/*
 * bpf_get_cgroup_classid
 *
 * 	Retrieve the classid for the current task, i.e. for the net_cls
 * 	cgroup to which *skb* belongs.
 *
 * 	This helper can be used on TC egress path, but not on ingress.
 *
 * 	The net_cls cgroup provides an interface to tag network packets
 * 	based on a user-provided identifier for all traffic coming from
 * 	the tasks belonging to the related cgroup. See also the related
 * 	kernel documentation, available from the Linux sources in file
 * 	*Documentation/admin-guide/cgroup-v1/net_cls.rst*.
 *
 * 	The Linux kernel has two versions for cgroups: there are
 * 	cgroups v1 and cgroups v2. Both are available to users, who can
 * 	use a mixture of them, but note that the net_cls cgroup is for
 * 	cgroup v1 only. This makes it incompatible with BPF programs
 * 	run on cgroups, which is a cgroup-v2-only feature (a socket can
 * 	only hold data for one version of cgroups at a time).
 *
 * 	This helper is only available is the kernel was compiled with
 * 	the **CONFIG_CGROUP_NET_CLASSID** configuration option set to
 * 	"**y**" or to "**m**".
 *
 * Returns
 * 	The classid, or 0 for the default unconfigured classid.
 */
static __u32 (*bpf_get_cgroup_classid)(struct __sk_buff *skb) = (void *) 17;

/*
 * bpf_skb_vlan_push
 *
 * 	Push a *vlan_tci* (VLAN tag control information) of protocol
 * 	*vlan_proto* to the packet associated to *skb*, then update
 * 	the checksum. Note that if *vlan_proto* is different from
 * 	**ETH_P_8021Q** and **ETH_P_8021AD**, it is considered to
 * 	be **ETH_P_8021Q**.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_vlan_push)(struct __sk_buff *skb, __be16 vlan_proto, __u16 vlan_tci) = (void *) 18;

/*
 * bpf_skb_vlan_pop
 *
 * 	Pop a VLAN header from the packet associated to *skb*.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_vlan_pop)(struct __sk_buff *skb) = (void *) 19;

/*
 * bpf_skb_get_tunnel_key
 *
 * 	Get tunnel metadata. This helper takes a pointer *key* to an
 * 	empty **struct bpf_tunnel_key** of **size**, that will be
 * 	filled with tunnel metadata for the packet associated to *skb*.
 * 	The *flags* can be set to **BPF_F_TUNINFO_IPV6**, which
 * 	indicates that the tunnel is based on IPv6 protocol instead of
 * 	IPv4.
 *
 * 	The **struct bpf_tunnel_key** is an object that generalizes the
 * 	principal parameters used by various tunneling protocols into a
 * 	single struct. This way, it can be used to easily make a
 * 	decision based on the contents of the encapsulation header,
 * 	"summarized" in this struct. In particular, it holds the IP
 * 	address of the remote end (IPv4 or IPv6, depending on the case)
 * 	in *key*\ **->remote_ipv4** or *key*\ **->remote_ipv6**. Also,
 * 	this struct exposes the *key*\ **->tunnel_id**, which is
 * 	generally mapped to a VNI (Virtual Network Identifier), making
 * 	it programmable together with the **bpf_skb_set_tunnel_key**\
 * 	() helper.
 *
 * 	Let's imagine that the following code is part of a program
 * 	attached to the TC ingress interface, on one end of a GRE
 * 	tunnel, and is supposed to filter out all messages coming from
 * 	remote ends with IPv4 address other than 10.0.0.1:
 *
 * 	::
 *
 * 		int ret;
 * 		struct bpf_tunnel_key key = {};
 *
 * 		ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
 * 		if (ret < 0)
 * 			return TC_ACT_SHOT;	// drop packet
 *
 * 		if (key.remote_ipv4 != 0x0a000001)
 * 			return TC_ACT_SHOT;	// drop packet
 *
 * 		return TC_ACT_OK;		// accept packet
 *
 * 	This interface can also be used with all encapsulation devices
 * 	that can operate in "collect metadata" mode: instead of having
 * 	one network device per specific configuration, the "collect
 * 	metadata" mode only requires a single device where the
 * 	configuration can be extracted from this helper.
 *
 * 	This can be used together with various tunnels such as VXLan,
 * 	Geneve, GRE or IP in IP (IPIP).
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_get_tunnel_key)(struct __sk_buff *skb, struct bpf_tunnel_key *key, __u32 size, __u64 flags) = (void *) 20;

/*
 * bpf_skb_set_tunnel_key
 *
 * 	Populate tunnel metadata for packet associated to *skb.* The
 * 	tunnel metadata is set to the contents of *key*, of *size*. The
 * 	*flags* can be set to a combination of the following values:
 *
 * 	**BPF_F_TUNINFO_IPV6**
 * 		Indicate that the tunnel is based on IPv6 protocol
 * 		instead of IPv4.
 * 	**BPF_F_ZERO_CSUM_TX**
 * 		For IPv4 packets, add a flag to tunnel metadata
 * 		indicating that checksum computation should be skipped
 * 		and checksum set to zeroes.
 * 	**BPF_F_DONT_FRAGMENT**
 * 		Add a flag to tunnel metadata indicating that the
 * 		packet should not be fragmented.
 * 	**BPF_F_SEQ_NUMBER**
 * 		Add a flag to tunnel metadata indicating that a
 * 		sequence number should be added to tunnel header before
 * 		sending the packet. This flag was added for GRE
 * 		encapsulation, but might be used with other protocols
 * 		as well in the future.
 *
 * 	Here is a typical usage on the transmit path:
 *
 * 	::
 *
 * 		struct bpf_tunnel_key key;
 * 		     populate key ...
 * 		bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
 * 		bpf_clone_redirect(skb, vxlan_dev_ifindex, 0);
 *
 * 	See also the description of the **bpf_skb_get_tunnel_key**\ ()
 * 	helper for additional information.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_set_tunnel_key)(struct __sk_buff *skb, struct bpf_tunnel_key *key, __u32 size, __u64 flags) = (void *) 21;

/*
 * bpf_perf_event_read
 *
 * 	Read the value of a perf event counter. This helper relies on a
 * 	*map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. The nature of
 * 	the perf event counter is selected when *map* is updated with
 * 	perf event file descriptors. The *map* is an array whose size
 * 	is the number of available CPUs, and each cell contains a value
 * 	relative to one CPU. The value to retrieve is indicated by
 * 	*flags*, that contains the index of the CPU to look up, masked
 * 	with **BPF_F_INDEX_MASK**. Alternatively, *flags* can be set to
 * 	**BPF_F_CURRENT_CPU** to indicate that the value for the
 * 	current CPU should be retrieved.
 *
 * 	Note that before Linux 4.13, only hardware perf event can be
 * 	retrieved.
 *
 * 	Also, be aware that the newer helper
 * 	**bpf_perf_event_read_value**\ () is recommended over
 * 	**bpf_perf_event_read**\ () in general. The latter has some ABI
 * 	quirks where error and counter value are used as a return code
 * 	(which is wrong to do since ranges may overlap). This issue is
 * 	fixed with **bpf_perf_event_read_value**\ (), which at the same
 * 	time provides more features over the **bpf_perf_event_read**\
 * 	() interface. Please refer to the description of
 * 	**bpf_perf_event_read_value**\ () for details.
 *
 * Returns
 * 	The value of the perf event counter read from the map, or a
 * 	negative error code in case of failure.
 */
static __u64 (*bpf_perf_event_read)(void *map, __u64 flags) = (void *) 22;

/*
 * bpf_redirect
 *
 * 	Redirect the packet to another net device of index *ifindex*.
 * 	This helper is somewhat similar to **bpf_clone_redirect**\
 * 	(), except that the packet is not cloned, which provides
 * 	increased performance.
 *
 * 	Except for XDP, both ingress and egress interfaces can be used
 * 	for redirection. The **BPF_F_INGRESS** value in *flags* is used
 * 	to make the distinction (ingress path is selected if the flag
 * 	is present, egress path otherwise). Currently, XDP only
 * 	supports redirection to the egress interface, and accepts no
 * 	flag at all.
 *
 * 	The same effect can also be attained with the more generic
 * 	**bpf_redirect_map**\ (), which uses a BPF map to store the
 * 	redirect target instead of providing it directly to the helper.
 *
 * Returns
 * 	For XDP, the helper returns **XDP_REDIRECT** on success or
 * 	**XDP_ABORTED** on error. For other program types, the values
 * 	are **TC_ACT_REDIRECT** on success or **TC_ACT_SHOT** on
 * 	error.
 */
static long (*bpf_redirect)(__u32 ifindex, __u64 flags) = (void *) 23;

/*
 * bpf_get_route_realm
 *
 * 	Retrieve the realm or the route, that is to say the
 * 	**tclassid** field of the destination for the *skb*. The
 * 	identifier retrieved is a user-provided tag, similar to the
 * 	one used with the net_cls cgroup (see description for
 * 	**bpf_get_cgroup_classid**\ () helper), but here this tag is
 * 	held by a route (a destination entry), not by a task.
 *
 * 	Retrieving this identifier works with the clsact TC egress hook
 * 	(see also **tc-bpf(8)**), or alternatively on conventional
 * 	classful egress qdiscs, but not on TC ingress path. In case of
 * 	clsact TC egress hook, this has the advantage that, internally,
 * 	the destination entry has not been dropped yet in the transmit
 * 	path. Therefore, the destination entry does not need to be
 * 	artificially held via **netif_keep_dst**\ () for a classful
 * 	qdisc until the *skb* is freed.
 *
 * 	This helper is available only if the kernel was compiled with
 * 	**CONFIG_IP_ROUTE_CLASSID** configuration option.
 *
 * Returns
 * 	The realm of the route for the packet associated to *skb*, or 0
 * 	if none was found.
 */
static __u32 (*bpf_get_route_realm)(struct __sk_buff *skb) = (void *) 24;

/*
 * bpf_perf_event_output
 *
 * 	Write raw *data* blob into a special BPF perf event held by
 * 	*map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf
 * 	event must have the following attributes: **PERF_SAMPLE_RAW**
 * 	as **sample_type**, **PERF_TYPE_SOFTWARE** as **type**, and
 * 	**PERF_COUNT_SW_BPF_OUTPUT** as **config**.
 *
 * 	The *flags* are used to indicate the index in *map* for which
 * 	the value must be put, masked with **BPF_F_INDEX_MASK**.
 * 	Alternatively, *flags* can be set to **BPF_F_CURRENT_CPU**
 * 	to indicate that the index of the current CPU core should be
 * 	used.
 *
 * 	The value to write, of *size*, is passed through eBPF stack and
 * 	pointed by *data*.
 *
 * 	The context of the program *ctx* needs also be passed to the
 * 	helper.
 *
 * 	On user space, a program willing to read the values needs to
 * 	call **perf_event_open**\ () on the perf event (either for
 * 	one or for all CPUs) and to store the file descriptor into the
 * 	*map*. This must be done before the eBPF program can send data
 * 	into it. An example is available in file
 * 	*samples/bpf/trace_output_user.c* in the Linux kernel source
 * 	tree (the eBPF program counterpart is in
 * 	*samples/bpf/trace_output_kern.c*).
 *
 * 	**bpf_perf_event_output**\ () achieves better performance
 * 	than **bpf_trace_printk**\ () for sharing data with user
 * 	space, and is much better suitable for streaming data from eBPF
 * 	programs.
 *
 * 	Note that this helper is not restricted to tracing use cases
 * 	and can be used with programs attached to TC or XDP as well,
 * 	where it allows for passing data to user space listeners. Data
 * 	can be:
 *
 * 	* Only custom structs,
 * 	* Only the packet payload, or
 * 	* A combination of both.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_perf_event_output)(void *ctx, void *map, __u64 flags, void *data, __u64 size) = (void *) 25;

/*
 * bpf_skb_load_bytes
 *
 * 	This helper was provided as an easy way to load data from a
 * 	packet. It can be used to load *len* bytes from *offset* from
 * 	the packet associated to *skb*, into the buffer pointed by
 * 	*to*.
 *
 * 	Since Linux 4.7, usage of this helper has mostly been replaced
 * 	by "direct packet access", enabling packet data to be
 * 	manipulated with *skb*\ **->data** and *skb*\ **->data_end**
 * 	pointing respectively to the first byte of packet data and to
 * 	the byte after the last byte of packet data. However, it
 * 	remains useful if one wishes to read large quantities of data
 * 	at once from a packet into the eBPF stack.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_load_bytes)(const void *skb, __u32 offset, void *to, __u32 len) = (void *) 26;

/*
 * bpf_get_stackid
 *
 * 	Walk a user or a kernel stack and return its id. To achieve
 * 	this, the helper needs *ctx*, which is a pointer to the context
 * 	on which the tracing program is executed, and a pointer to a
 * 	*map* of type **BPF_MAP_TYPE_STACK_TRACE**.
 *
 * 	The last argument, *flags*, holds the number of stack frames to
 * 	skip (from 0 to 255), masked with
 * 	**BPF_F_SKIP_FIELD_MASK**. The next bits can be used to set
 * 	a combination of the following flags:
 *
 * 	**BPF_F_USER_STACK**
 * 		Collect a user space stack instead of a kernel stack.
 * 	**BPF_F_FAST_STACK_CMP**
 * 		Compare stacks by hash only.
 * 	**BPF_F_REUSE_STACKID**
 * 		If two different stacks hash into the same *stackid*,
 * 		discard the old one.
 *
 * 	The stack id retrieved is a 32 bit long integer handle which
 * 	can be further combined with other data (including other stack
 * 	ids) and used as a key into maps. This can be useful for
 * 	generating a variety of graphs (such as flame graphs or off-cpu
 * 	graphs).
 *
 * 	For walking a stack, this helper is an improvement over
 * 	**bpf_probe_read**\ (), which can be used with unrolled loops
 * 	but is not efficient and consumes a lot of eBPF instructions.
 * 	Instead, **bpf_get_stackid**\ () can collect up to
 * 	**PERF_MAX_STACK_DEPTH** both kernel and user frames. Note that
 * 	this limit can be controlled with the **sysctl** program, and
 * 	that it should be manually increased in order to profile long
 * 	user stacks (such as stacks for Java programs). To do so, use:
 *
 * 	::
 *
 * 		# sysctl kernel.perf_event_max_stack=<new value>
 *
 * Returns
 * 	The positive or null stack id on success, or a negative error
 * 	in case of failure.
 */
static long (*bpf_get_stackid)(void *ctx, void *map, __u64 flags) = (void *) 27;

/*
 * bpf_csum_diff
 *
 * 	Compute a checksum difference, from the raw buffer pointed by
 * 	*from*, of length *from_size* (that must be a multiple of 4),
 * 	towards the raw buffer pointed by *to*, of size *to_size*
 * 	(same remark). An optional *seed* can be added to the value
 * 	(this can be cascaded, the seed may come from a previous call
 * 	to the helper).
 *
 * 	This is flexible enough to be used in several ways:
 *
 * 	* With *from_size* == 0, *to_size* > 0 and *seed* set to
 * 	  checksum, it can be used when pushing new data.
 * 	* With *from_size* > 0, *to_size* == 0 and *seed* set to
 * 	  checksum, it can be used when removing data from a packet.
 * 	* With *from_size* > 0, *to_size* > 0 and *seed* set to 0, it
 * 	  can be used to compute a diff. Note that *from_size* and
 * 	  *to_size* do not need to be equal.
 *
 * 	This helper can be used in combination with
 * 	**bpf_l3_csum_replace**\ () and **bpf_l4_csum_replace**\ (), to
 * 	which one can feed in the difference computed with
 * 	**bpf_csum_diff**\ ().
 *
 * Returns
 * 	The checksum result, or a negative error code in case of
 * 	failure.
 */
static __s64 (*bpf_csum_diff)(__be32 *from, __u32 from_size, __be32 *to, __u32 to_size, __wsum seed) = (void *) 28;

/*
 * bpf_skb_get_tunnel_opt
 *
 * 	Retrieve tunnel options metadata for the packet associated to
 * 	*skb*, and store the raw tunnel option data to the buffer *opt*
 * 	of *size*.
 *
 * 	This helper can be used with encapsulation devices that can
 * 	operate in "collect metadata" mode (please refer to the related
 * 	note in the description of **bpf_skb_get_tunnel_key**\ () for
 * 	more details). A particular example where this can be used is
 * 	in combination with the Geneve encapsulation protocol, where it
 * 	allows for pushing (with **bpf_skb_get_tunnel_opt**\ () helper)
 * 	and retrieving arbitrary TLVs (Type-Length-Value headers) from
 * 	the eBPF program. This allows for full customization of these
 * 	headers.
 *
 * Returns
 * 	The size of the option data retrieved.
 */
static long (*bpf_skb_get_tunnel_opt)(struct __sk_buff *skb, void *opt, __u32 size) = (void *) 29;

/*
 * bpf_skb_set_tunnel_opt
 *
 * 	Set tunnel options metadata for the packet associated to *skb*
 * 	to the option data contained in the raw buffer *opt* of *size*.
 *
 * 	See also the description of the **bpf_skb_get_tunnel_opt**\ ()
 * 	helper for additional information.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_set_tunnel_opt)(struct __sk_buff *skb, void *opt, __u32 size) = (void *) 30;

/*
 * bpf_skb_change_proto
 *
 * 	Change the protocol of the *skb* to *proto*. Currently
 * 	supported are transition from IPv4 to IPv6, and from IPv6 to
 * 	IPv4. The helper takes care of the groundwork for the
 * 	transition, including resizing the socket buffer. The eBPF
 * 	program is expected to fill the new headers, if any, via
 * 	**skb_store_bytes**\ () and to recompute the checksums with
 * 	**bpf_l3_csum_replace**\ () and **bpf_l4_csum_replace**\
 * 	(). The main case for this helper is to perform NAT64
 * 	operations out of an eBPF program.
 *
 * 	Internally, the GSO type is marked as dodgy so that headers are
 * 	checked and segments are recalculated by the GSO/GRO engine.
 * 	The size for GSO target is adapted as well.
 *
 * 	All values for *flags* are reserved for future usage, and must
 * 	be left at zero.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_change_proto)(struct __sk_buff *skb, __be16 proto, __u64 flags) = (void *) 31;

/*
 * bpf_skb_change_type
 *
 * 	Change the packet type for the packet associated to *skb*. This
 * 	comes down to setting *skb*\ **->pkt_type** to *type*, except
 * 	the eBPF program does not have a write access to *skb*\
 * 	**->pkt_type** beside this helper. Using a helper here allows
 * 	for graceful handling of errors.
 *
 * 	The major use case is to change incoming *skb*s to
 * 	**PACKET_HOST** in a programmatic way instead of having to
 * 	recirculate via **redirect**\ (..., **BPF_F_INGRESS**), for
 * 	example.
 *
 * 	Note that *type* only allows certain values. At this time, they
 * 	are:
 *
 * 	**PACKET_HOST**
 * 		Packet is for us.
 * 	**PACKET_BROADCAST**
 * 		Send packet to all.
 * 	**PACKET_MULTICAST**
 * 		Send packet to group.
 * 	**PACKET_OTHERHOST**
 * 		Send packet to someone else.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_change_type)(struct __sk_buff *skb, __u32 type) = (void *) 32;

/*
 * bpf_skb_under_cgroup
 *
 * 	Check whether *skb* is a descendant of the cgroup2 held by
 * 	*map* of type **BPF_MAP_TYPE_CGROUP_ARRAY**, at *index*.
 *
 * Returns
 * 	The return value depends on the result of the test, and can be:
 *
 * 	* 0, if the *skb* failed the cgroup2 descendant test.
 * 	* 1, if the *skb* succeeded the cgroup2 descendant test.
 * 	* A negative error code, if an error occurred.
 */
static long (*bpf_skb_under_cgroup)(struct __sk_buff *skb, void *map, __u32 index) = (void *) 33;

/*
 * bpf_get_hash_recalc
 *
 * 	Retrieve the hash of the packet, *skb*\ **->hash**. If it is
 * 	not set, in particular if the hash was cleared due to mangling,
 * 	recompute this hash. Later accesses to the hash can be done
 * 	directly with *skb*\ **->hash**.
 *
 * 	Calling **bpf_set_hash_invalid**\ (), changing a packet
 * 	prototype with **bpf_skb_change_proto**\ (), or calling
 * 	**bpf_skb_store_bytes**\ () with the
 * 	**BPF_F_INVALIDATE_HASH** are actions susceptible to clear
 * 	the hash and to trigger a new computation for the next call to
 * 	**bpf_get_hash_recalc**\ ().
 *
 * Returns
 * 	The 32-bit hash.
 */
static __u32 (*bpf_get_hash_recalc)(struct __sk_buff *skb) = (void *) 34;

/*
 * bpf_get_current_task
 *
 *
 * Returns
 * 	A pointer to the current task struct.
 */
static __u64 (*bpf_get_current_task)(void) = (void *) 35;

/*
 * bpf_probe_write_user
 *
 * 	Attempt in a safe way to write *len* bytes from the buffer
 * 	*src* to *dst* in memory. It only works for threads that are in
 * 	user context, and *dst* must be a valid user space address.
 *
 * 	This helper should not be used to implement any kind of
 * 	security mechanism because of TOC-TOU attacks, but rather to
 * 	debug, divert, and manipulate execution of semi-cooperative
 * 	processes.
 *
 * 	Keep in mind that this feature is meant for experiments, and it
 * 	has a risk of crashing the system and running programs.
 * 	Therefore, when an eBPF program using this helper is attached,
 * 	a warning including PID and process name is printed to kernel
 * 	logs.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_probe_write_user)(void *dst, const void *src, __u32 len) = (void *) 36;

/*
 * bpf_current_task_under_cgroup
 *
 * 	Check whether the probe is being run is the context of a given
 * 	subset of the cgroup2 hierarchy. The cgroup2 to test is held by
 * 	*map* of type **BPF_MAP_TYPE_CGROUP_ARRAY**, at *index*.
 *
 * Returns
 * 	The return value depends on the result of the test, and can be:
 *
 * 	* 0, if current task belongs to the cgroup2.
 * 	* 1, if current task does not belong to the cgroup2.
 * 	* A negative error code, if an error occurred.
 */
static long (*bpf_current_task_under_cgroup)(void *map, __u32 index) = (void *) 37;

/*
 * bpf_skb_change_tail
 *
 * 	Resize (trim or grow) the packet associated to *skb* to the
 * 	new *len*. The *flags* are reserved for future usage, and must
 * 	be left at zero.
 *
 * 	The basic idea is that the helper performs the needed work to
 * 	change the size of the packet, then the eBPF program rewrites
 * 	the rest via helpers like **bpf_skb_store_bytes**\ (),
 * 	**bpf_l3_csum_replace**\ (), **bpf_l3_csum_replace**\ ()
 * 	and others. This helper is a slow path utility intended for
 * 	replies with control messages. And because it is targeted for
 * 	slow path, the helper itself can afford to be slow: it
 * 	implicitly linearizes, unclones and drops offloads from the
 * 	*skb*.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_change_tail)(struct __sk_buff *skb, __u32 len, __u64 flags) = (void *) 38;

/*
 * bpf_skb_pull_data
 *
 * 	Pull in non-linear data in case the *skb* is non-linear and not
 * 	all of *len* are part of the linear section. Make *len* bytes
 * 	from *skb* readable and writable. If a zero value is passed for
 * 	*len*, then the whole length of the *skb* is pulled.
 *
 * 	This helper is only needed for reading and writing with direct
 * 	packet access.
 *
 * 	For direct packet access, testing that offsets to access
 * 	are within packet boundaries (test on *skb*\ **->data_end**) is
 * 	susceptible to fail if offsets are invalid, or if the requested
 * 	data is in non-linear parts of the *skb*. On failure the
 * 	program can just bail out, or in the case of a non-linear
 * 	buffer, use a helper to make the data available. The
 * 	**bpf_skb_load_bytes**\ () helper is a first solution to access
 * 	the data. Another one consists in using **bpf_skb_pull_data**
 * 	to pull in once the non-linear parts, then retesting and
 * 	eventually access the data.
 *
 * 	At the same time, this also makes sure the *skb* is uncloned,
 * 	which is a necessary condition for direct write. As this needs
 * 	to be an invariant for the write part only, the verifier
 * 	detects writes and adds a prologue that is calling
 * 	**bpf_skb_pull_data()** to effectively unclone the *skb* from
 * 	the very beginning in case it is indeed cloned.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_pull_data)(struct __sk_buff *skb, __u32 len) = (void *) 39;

/*
 * bpf_csum_update
 *
 * 	Add the checksum *csum* into *skb*\ **->csum** in case the
 * 	driver has supplied a checksum for the entire packet into that
 * 	field. Return an error otherwise. This helper is intended to be
 * 	used in combination with **bpf_csum_diff**\ (), in particular
 * 	when the checksum needs to be updated after data has been
 * 	written into the packet through direct packet access.
 *
 * Returns
 * 	The checksum on success, or a negative error code in case of
 * 	failure.
 */
static __s64 (*bpf_csum_update)(struct __sk_buff *skb, __wsum csum) = (void *) 40;

/*
 * bpf_set_hash_invalid
 *
 * 	Invalidate the current *skb*\ **->hash**. It can be used after
 * 	mangling on headers through direct packet access, in order to
 * 	indicate that the hash is outdated and to trigger a
 * 	recalculation the next time the kernel tries to access this
 * 	hash or when the **bpf_get_hash_recalc**\ () helper is called.
 *
 */
static void (*bpf_set_hash_invalid)(struct __sk_buff *skb) = (void *) 41;

/*
 * bpf_get_numa_node_id
 *
 * 	Return the id of the current NUMA node. The primary use case
 * 	for this helper is the selection of sockets for the local NUMA
 * 	node, when the program is attached to sockets using the
 * 	**SO_ATTACH_REUSEPORT_EBPF** option (see also **socket(7)**),
 * 	but the helper is also available to other eBPF program types,
 * 	similarly to **bpf_get_smp_processor_id**\ ().
 *
 * Returns
 * 	The id of current NUMA node.
 */
static long (*bpf_get_numa_node_id)(void) = (void *) 42;

/*
 * bpf_skb_change_head
 *
 * 	Grows headroom of packet associated to *skb* and adjusts the
 * 	offset of the MAC header accordingly, adding *len* bytes of
 * 	space. It automatically extends and reallocates memory as
 * 	required.
 *
 * 	This helper can be used on a layer 3 *skb* to push a MAC header
 * 	for redirection into a layer 2 device.
 *
 * 	All values for *flags* are reserved for future usage, and must
 * 	be left at zero.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_change_head)(struct __sk_buff *skb, __u32 len, __u64 flags) = (void *) 43;

/*
 * bpf_xdp_adjust_head
 *
 * 	Adjust (move) *xdp_md*\ **->data** by *delta* bytes. Note that
 * 	it is possible to use a negative value for *delta*. This helper
 * 	can be used to prepare the packet for pushing or popping
 * 	headers.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_xdp_adjust_head)(struct xdp_md *xdp_md, int delta) = (void *) 44;

/*
 * bpf_probe_read_str
 *
 * 	Copy a NUL terminated string from an unsafe kernel address
 * 	*unsafe_ptr* to *dst*. See **bpf_probe_read_kernel_str**\ () for
 * 	more details.
 *
 * 	Generally, use **bpf_probe_read_user_str**\ () or
 * 	**bpf_probe_read_kernel_str**\ () instead.
 *
 * Returns
 * 	On success, the strictly positive length of the string,
 * 	including the trailing NUL character. On error, a negative
 * 	value.
 */
static long (*bpf_probe_read_str)(void *dst, __u32 size, const void *unsafe_ptr) = (void *) 45;

/*
 * bpf_get_socket_cookie
 *
 * 	If the **struct sk_buff** pointed by *skb* has a known socket,
 * 	retrieve the cookie (generated by the kernel) of this socket.
 * 	If no cookie has been set yet, generate a new cookie. Once
 * 	generated, the socket cookie remains stable for the life of the
 * 	socket. This helper can be useful for monitoring per socket
 * 	networking traffic statistics as it provides a global socket
 * 	identifier that can be assumed unique.
 *
 * Returns
 * 	A 8-byte long unique number on success, or 0 if the socket
 * 	field is missing inside *skb*.
 */
static __u64 (*bpf_get_socket_cookie)(void *ctx) = (void *) 46;

/*
 * bpf_get_socket_uid
 *
 *
 * Returns
 * 	The owner UID of the socket associated to *skb*. If the socket
 * 	is **NULL**, or if it is not a full socket (i.e. if it is a
 * 	time-wait or a request socket instead), **overflowuid** value
 * 	is returned (note that **overflowuid** might also be the actual
 * 	UID value for the socket).
 */
static __u32 (*bpf_get_socket_uid)(struct __sk_buff *skb) = (void *) 47;

/*
 * bpf_set_hash
 *
 * 	Set the full hash for *skb* (set the field *skb*\ **->hash**)
 * 	to value *hash*.
 *
 * Returns
 * 	0
 */
static long (*bpf_set_hash)(struct __sk_buff *skb, __u32 hash) = (void *) 48;

/*
 * bpf_setsockopt
 *
 * 	Emulate a call to **setsockopt()** on the socket associated to
 * 	*bpf_socket*, which must be a full socket. The *level* at
 * 	which the option resides and the name *optname* of the option
 * 	must be specified, see **setsockopt(2)** for more information.
 * 	The option value of length *optlen* is pointed by *optval*.
 *
 * 	*bpf_socket* should be one of the following:
 *
 * 	* **struct bpf_sock_ops** for **BPF_PROG_TYPE_SOCK_OPS**.
 * 	* **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**
 * 	  and **BPF_CGROUP_INET6_CONNECT**.
 *
 * 	This helper actually implements a subset of **setsockopt()**.
 * 	It supports the following *level*\ s:
 *
 * 	* **SOL_SOCKET**, which supports the following *optname*\ s:
 * 	  **SO_RCVBUF**, **SO_SNDBUF**, **SO_MAX_PACING_RATE**,
 * 	  **SO_PRIORITY**, **SO_RCVLOWAT**, **SO_MARK**,
 * 	  **SO_BINDTODEVICE**, **SO_KEEPALIVE**.
 * 	* **IPPROTO_TCP**, which supports the following *optname*\ s:
 * 	  **TCP_CONGESTION**, **TCP_BPF_IW**,
 * 	  **TCP_BPF_SNDCWND_CLAMP**, **TCP_SAVE_SYN**,
 * 	  **TCP_KEEPIDLE**, **TCP_KEEPINTVL**, **TCP_KEEPCNT**,
 * 	  **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**.
 * 	* **IPPROTO_IP**, which supports *optname* **IP_TOS**.
 * 	* **IPPROTO_IPV6**, which supports *optname* **IPV6_TCLASS**.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_setsockopt)(void *bpf_socket, int level, int optname, void *optval, int optlen) = (void *) 49;

/*
 * bpf_skb_adjust_room
 *
 * 	Grow or shrink the room for data in the packet associated to
 * 	*skb* by *len_diff*, and according to the selected *mode*.
 *
 * 	By default, the helper will reset any offloaded checksum
 * 	indicator of the skb to CHECKSUM_NONE. This can be avoided
 * 	by the following flag:
 *
 * 	* **BPF_F_ADJ_ROOM_NO_CSUM_RESET**: Do not reset offloaded
 * 	  checksum data of the skb to CHECKSUM_NONE.
 *
 * 	There are two supported modes at this time:
 *
 * 	* **BPF_ADJ_ROOM_MAC**: Adjust room at the mac layer
 * 	  (room space is added or removed below the layer 2 header).
 *
 * 	* **BPF_ADJ_ROOM_NET**: Adjust room at the network layer
 * 	  (room space is added or removed below the layer 3 header).
 *
 * 	The following flags are supported at this time:
 *
 * 	* **BPF_F_ADJ_ROOM_FIXED_GSO**: Do not adjust gso_size.
 * 	  Adjusting mss in this way is not allowed for datagrams.
 *
 * 	* **BPF_F_ADJ_ROOM_ENCAP_L3_IPV4**,
 * 	  **BPF_F_ADJ_ROOM_ENCAP_L3_IPV6**:
 * 	  Any new space is reserved to hold a tunnel header.
 * 	  Configure skb offsets and other fields accordingly.
 *
 * 	* **BPF_F_ADJ_ROOM_ENCAP_L4_GRE**,
 * 	  **BPF_F_ADJ_ROOM_ENCAP_L4_UDP**:
 * 	  Use with ENCAP_L3 flags to further specify the tunnel type.
 *
 * 	* **BPF_F_ADJ_ROOM_ENCAP_L2**\ (*len*):
 * 	  Use with ENCAP_L3/L4 flags to further specify the tunnel
 * 	  type; *len* is the length of the inner MAC header.
 *
 * 	* **BPF_F_ADJ_ROOM_ENCAP_L2_ETH**:
 * 	  Use with BPF_F_ADJ_ROOM_ENCAP_L2 flag to further specify the
 * 	  L2 type as Ethernet.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_skb_adjust_room)(struct __sk_buff *skb, __s32 len_diff, __u32 mode, __u64 flags) = (void *) 50;

/*
 * bpf_redirect_map
 *
 * 	Redirect the packet to the endpoint referenced by *map* at
 * 	index *key*. Depending on its type, this *map* can contain
 * 	references to net devices (for forwarding packets through other
 * 	ports), or to CPUs (for redirecting XDP frames to another CPU;
 * 	but this is only implemented for native XDP (with driver
 * 	support) as of this writing).
 *
 * 	The lower two bits of *flags* are used as the return code if
 * 	the map lookup fails. This is so that the return value can be
 * 	one of the XDP program return codes up to **XDP_TX**, as chosen
 * 	by the caller. The higher bits of *flags* can be set to
 * 	BPF_F_BROADCAST or BPF_F_EXCLUDE_INGRESS as defined below.
 *
 * 	With BPF_F_BROADCAST the packet will be broadcasted to all the
 * 	interfaces in the map, with BPF_F_EXCLUDE_INGRESS the ingress
 * 	interface will be excluded when do broadcasting.
 *
 * 	See also **bpf_redirect**\ (), which only supports redirecting
 * 	to an ifindex, but doesn't require a map to do so.
 *
 * Returns
 * 	**XDP_REDIRECT** on success, or the value of the two lower bits
 * 	of the *flags* argument on error.
 */
static long (*bpf_redirect_map)(void *map, __u32 key, __u64 flags) = (void *) 51;

/*
 * bpf_sk_redirect_map
 *
 * 	Redirect the packet to the socket referenced by *map* (of type
 * 	**BPF_MAP_TYPE_SOCKMAP**) at index *key*. Both ingress and
 * 	egress interfaces can be used for redirection. The
 * 	**BPF_F_INGRESS** value in *flags* is used to make the
 * 	distinction (ingress path is selected if the flag is present,
 * 	egress path otherwise). This is the only flag supported for now.
 *
 * Returns
 * 	**SK_PASS** on success, or **SK_DROP** on error.
 */
static long (*bpf_sk_redirect_map)(struct __sk_buff *skb, void *map, __u32 key, __u64 flags) = (void *) 52;

/*
 * bpf_sock_map_update
 *
 * 	Add an entry to, or update a *map* referencing sockets. The
 * 	*skops* is used as a new value for the entry associated to
 * 	*key*. *flags* is one of:
 *
 * 	**BPF_NOEXIST**
 * 		The entry for *key* must not exist in the map.
 * 	**BPF_EXIST**
 * 		The entry for *key* must already exist in the map.
 * 	**BPF_ANY**
 * 		No condition on the existence of the entry for *key*.
 *
 * 	If the *map* has eBPF programs (parser and verdict), those will
 * 	be inherited by the socket being added. If the socket is
 * 	already attached to eBPF programs, this results in an error.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_sock_map_update)(struct bpf_sock_ops *skops, void *map, void *key, __u64 flags) = (void *) 53;

/*
 * bpf_xdp_adjust_meta
 *
 * 	Adjust the address pointed by *xdp_md*\ **->data_meta** by
 * 	*delta* (which can be positive or negative). Note that this
 * 	operation modifies the address stored in *xdp_md*\ **->data**,
 * 	so the latter must be loaded only after the helper has been
 * 	called.
 *
 * 	The use of *xdp_md*\ **->data_meta** is optional and programs
 * 	are not required to use it. The rationale is that when the
 * 	packet is processed with XDP (e.g. as DoS filter), it is
 * 	possible to push further meta data along with it before passing
 * 	to the stack, and to give the guarantee that an ingress eBPF
 * 	program attached as a TC classifier on the same device can pick
 * 	this up for further post-processing. Since TC works with socket
 * 	buffers, it remains possible to set from XDP the **mark** or
 * 	**priority** pointers, or other pointers for the socket buffer.
 * 	Having this scratch space generic and programmable allows for
 * 	more flexibility as the user is free to store whatever meta
 * 	data they need.
 *
 * 	A call to this helper is susceptible to change the underlying
 * 	packet buffer. Therefore, at load time, all checks on pointers
 * 	previously done by the verifier are invalidated and must be
 * 	performed again, if the helper is used in combination with
 * 	direct packet access.
 *
 * Returns
 * 	0 on success, or a negative error in case of failure.
 */
static long (*bpf_xdp_adjust_meta)(struct xdp_md *xdp_md, int delta) = (void *) 54;

/*
 * bpf_perf_event_read_value
 *
 * 	Read the value of a perf event counter, and store it into *buf*
 * 	of size *buf_size*. This helper relies 
Download .txt
gitextract_q11y6zpa/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   └── feature-request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       └── release.yml
├── .gitignore
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── cli/
│   └── main.go
├── docs/
│   ├── design/
│   │   ├── context-propagation.md
│   │   └── manual-instrumentation.md
│   ├── getting-started/
│   │   ├── README.md
│   │   ├── emojivoto/
│   │   │   ├── emoji.yml
│   │   │   ├── kustomization.yml
│   │   │   ├── ns.yml
│   │   │   ├── vote-bot.yml
│   │   │   ├── voting.yml
│   │   │   └── web.yml
│   │   ├── emojivoto-instrumented.yaml
│   │   └── jaeger.yaml
│   └── how-it-works.md
├── go.mod
├── go.sum
├── include/
│   ├── alloc.h
│   ├── arguments.h
│   ├── common.h
│   ├── go_context.h
│   ├── go_types.h
│   ├── libbpf/
│   │   ├── bpf.h
│   │   ├── bpf_core_read.h
│   │   ├── bpf_endian.h
│   │   ├── bpf_helper_defs.h
│   │   ├── bpf_helpers.h
│   │   ├── bpf_tracing.h
│   │   ├── btf.h
│   │   ├── libbpf.h
│   │   ├── libbpf_common.h
│   │   ├── libbpf_legacy.h
│   │   ├── libbpf_version.h
│   │   ├── skel_internal.h
│   │   └── xsk.h
│   ├── span_context.h
│   └── utils.h
└── pkg/
    ├── errors/
    │   └── errors.go
    ├── inject/
    │   ├── data.go
    │   ├── injector.go
    │   └── offset_results.json
    ├── instrumentors/
    │   ├── allocator/
    │   │   └── allocator_linux.go
    │   ├── api.go
    │   ├── bpf/
    │   │   ├── github.com/
    │   │   │   └── gorilla/
    │   │   │       └── mux/
    │   │   │           ├── bpf/
    │   │   │           │   └── probe.bpf.c
    │   │   │           └── probe.go
    │   │   ├── google/
    │   │   │   └── golang/
    │   │   │       └── org/
    │   │   │           └── grpc/
    │   │   │               ├── bpf/
    │   │   │               │   └── probe.bpf.c
    │   │   │               ├── probe.go
    │   │   │               └── server/
    │   │   │                   ├── bpf/
    │   │   │                   │   └── probe.bpf.c
    │   │   │                   └── probe.go
    │   │   └── net/
    │   │       └── http/
    │   │           └── server/
    │   │               ├── bpf/
    │   │               │   └── probe.bpf.c
    │   │               └── probe.go
    │   ├── bpffs/
    │   │   └── bpfsfs.go
    │   ├── context/
    │   │   ├── inst_context.go
    │   │   └── span_context.go
    │   ├── events/
    │   │   └── event.go
    │   ├── manager.go
    │   └── runner.go
    ├── log/
    │   └── logger.go
    ├── opentelemetry/
    │   ├── controller.go
    │   └── id_generator.go
    └── process/
        ├── analyze.go
        ├── args.go
        ├── discover.go
        ├── funcs_nonstripped.go
        ├── funcs_stripped.go
        ├── module.go
        ├── ptrace/
        │   ├── cwrapper_linux.go
        │   ├── ptrace_linux.go
        │   ├── ptrace_linux_amd64.go
        │   └── ptrace_linux_arm64.go
        ├── ret_linux_amd64.go
        └── ret_linux_arm64.go
Download .txt
SYMBOL INDEX (875 symbols across 51 files)

FILE: cli/main.go
  function main (line 16) | func main() {

FILE: include/alloc.h
  function __always_inline (line 18) | static __always_inline u64 get_area_start() {
  function __always_inline (line 32) | static __always_inline u64 get_area_end(u64 start) {
  function __always_inline (line 46) | static __always_inline void* write_target_data(void* data, s32 size) {

FILE: include/arguments.h
  type pt_regs (line 9) | struct pt_regs
  type pt_regs (line 34) | struct pt_regs
  type pt_regs (line 40) | struct pt_regs

FILE: include/common.h
  type __u8 (line 8) | typedef unsigned char __u8;
  type __s16 (line 9) | typedef short int __s16;
  type __u16 (line 10) | typedef short unsigned int __u16;
  type __s32 (line 11) | typedef int __s32;
  type __u32 (line 12) | typedef unsigned int __u32;
  type __s64 (line 13) | typedef long long int __s64;
  type __u64 (line 14) | typedef long long unsigned int __u64;
  type __u8 (line 15) | typedef __u8 u8;
  type __s16 (line 16) | typedef __s16 s16;
  type __u16 (line 17) | typedef __u16 u16;
  type __s32 (line 18) | typedef __s32 s32;
  type __u32 (line 19) | typedef __u32 u32;
  type __s64 (line 20) | typedef __s64 s64;
  type __u64 (line 21) | typedef __u64 u64;
  type __u16 (line 22) | typedef __u16 __le16;
  type __u16 (line 23) | typedef __u16 __be16;
  type __u32 (line 24) | typedef __u32 __be32;
  type __u64 (line 25) | typedef __u64 __be64;
  type __u32 (line 26) | typedef __u32 __wsum;
  type bpf_map_type (line 28) | enum bpf_map_type {
  type pt_regs (line 74) | struct pt_regs {
  type user_pt_regs (line 98) | struct user_pt_regs {
  type pt_regs (line 105) | struct pt_regs {

FILE: include/go_context.h
  function __always_inline (line 5) | static __always_inline void* find_context_in_map(void *ctx, void *contex...

FILE: include/go_types.h
  type go_string (line 7) | struct go_string {
  type go_slice (line 12) | struct go_slice {
  type go_slice_user_ptr (line 18) | struct go_slice_user_ptr {
  type go_iface (line 24) | struct go_iface {
  function go_string (line 29) | go_string write_user_go_string(char* str, u32 len) {
  function __always_inline (line 47) | static __always_inline void append_item_to_slice(struct go_slice *slice,...

FILE: include/libbpf/bpf.h
  type bpf_create_map_attr (line 37) | struct bpf_create_map_attr {
  type bpf_create_map_attr (line 56) | struct bpf_create_map_attr
  type bpf_map_type (line 57) | enum bpf_map_type
  type bpf_map_type (line 60) | enum bpf_map_type
  type bpf_map_type (line 63) | enum bpf_map_type
  type bpf_map_type (line 65) | enum bpf_map_type
  type bpf_map_type (line 69) | enum bpf_map_type
  type bpf_load_program_attr (line 74) | struct bpf_load_program_attr {
  type bpf_load_program_attr (line 106) | struct bpf_load_program_attr
  type bpf_prog_type (line 108) | enum bpf_prog_type
  type bpf_insn (line 109) | struct bpf_insn
  type bpf_prog_type (line 112) | enum bpf_prog_type
  type bpf_insn (line 113) | struct bpf_insn
  type bpf_map_batch_opts (line 133) | struct bpf_map_batch_opts {
  type bpf_map_batch_opts (line 142) | struct bpf_map_batch_opts
  type bpf_map_batch_opts (line 145) | struct bpf_map_batch_opts
  type bpf_map_batch_opts (line 149) | struct bpf_map_batch_opts
  type bpf_map_batch_opts (line 152) | struct bpf_map_batch_opts
  type bpf_prog_attach_opts (line 157) | struct bpf_prog_attach_opts {
  type bpf_attach_type (line 165) | enum bpf_attach_type
  type bpf_attach_type (line 167) | enum bpf_attach_type
  type bpf_prog_attach_opts (line 168) | struct bpf_prog_attach_opts
  type bpf_attach_type (line 169) | enum bpf_attach_type
  type bpf_attach_type (line 171) | enum bpf_attach_type
  type bpf_link_create_opts (line 174) | struct bpf_link_create_opts {
  type bpf_attach_type (line 190) | enum bpf_attach_type
  type bpf_link_create_opts (line 191) | struct bpf_link_create_opts
  type bpf_link_update_opts (line 195) | struct bpf_link_update_opts {
  type bpf_link_update_opts (line 203) | struct bpf_link_update_opts
  type bpf_prog_test_run_attr (line 207) | struct bpf_prog_test_run_attr {
  type bpf_prog_test_run_attr (line 224) | struct bpf_prog_test_run_attr
  type bpf_attach_type (line 242) | enum bpf_attach_type
  type bpf_stats_type (line 252) | enum bpf_stats_type
  type bpf_stats_type (line 253) | enum bpf_stats_type
  type bpf_prog_bind_opts (line 255) | struct bpf_prog_bind_opts {
  type bpf_prog_bind_opts (line 262) | struct bpf_prog_bind_opts
  type bpf_test_run_opts (line 264) | struct bpf_test_run_opts {
  type bpf_test_run_opts (line 287) | struct bpf_test_run_opts

FILE: include/libbpf/bpf_core_read.h
  type bpf_field_info_kind (line 13) | enum bpf_field_info_kind {
  type bpf_type_id_kind (line 23) | enum bpf_type_id_kind {
  type bpf_type_info_kind (line 29) | enum bpf_type_info_kind {
  type bpf_enum_value_kind (line 35) | enum bpf_enum_value_kind {

FILE: include/libbpf/bpf_helper_defs.h
  type bpf_fib_lookup (line 4) | struct bpf_fib_lookup
  type bpf_sk_lookup (line 5) | struct bpf_sk_lookup
  type bpf_perf_event_data (line 6) | struct bpf_perf_event_data
  type bpf_perf_event_value (line 7) | struct bpf_perf_event_value
  type bpf_pidns_info (line 8) | struct bpf_pidns_info
  type bpf_redir_neigh (line 9) | struct bpf_redir_neigh
  type bpf_sock (line 10) | struct bpf_sock
  type bpf_sock_addr (line 11) | struct bpf_sock_addr
  type bpf_sock_ops (line 12) | struct bpf_sock_ops
  type bpf_sock_tuple (line 13) | struct bpf_sock_tuple
  type bpf_spin_lock (line 14) | struct bpf_spin_lock
  type bpf_sysctl (line 15) | struct bpf_sysctl
  type bpf_tcp_sock (line 16) | struct bpf_tcp_sock
  type bpf_tunnel_key (line 17) | struct bpf_tunnel_key
  type bpf_xfrm_state (line 18) | struct bpf_xfrm_state
  type linux_binprm (line 19) | struct linux_binprm
  type pt_regs (line 20) | struct pt_regs
  type sk_reuseport_md (line 21) | struct sk_reuseport_md
  type sockaddr (line 22) | struct sockaddr
  type tcphdr (line 23) | struct tcphdr
  type seq_file (line 24) | struct seq_file
  type tcp6_sock (line 25) | struct tcp6_sock
  type tcp_sock (line 26) | struct tcp_sock
  type tcp_timewait_sock (line 27) | struct tcp_timewait_sock
  type tcp_request_sock (line 28) | struct tcp_request_sock
  type udp6_sock (line 29) | struct udp6_sock
  type task_struct (line 30) | struct task_struct
  type __sk_buff (line 31) | struct __sk_buff
  type sk_msg_md (line 32) | struct sk_msg_md
  type xdp_md (line 33) | struct xdp_md
  type path (line 34) | struct path
  type btf_ptr (line 35) | struct btf_ptr
  type inode (line 36) | struct inode
  type socket (line 37) | struct socket
  type file (line 38) | struct file
  type bpf_timer (line 39) | struct bpf_timer
  type __sk_buff (line 221) | struct __sk_buff
  type __sk_buff (line 250) | struct __sk_buff
  type __sk_buff (line 286) | struct __sk_buff
  type __sk_buff (line 349) | struct __sk_buff
  type __sk_buff (line 416) | struct __sk_buff
  type __sk_buff (line 436) | struct __sk_buff
  type __sk_buff (line 452) | struct __sk_buff
  type __sk_buff (line 507) | struct __sk_buff
  type bpf_tunnel_key (line 507) | struct bpf_tunnel_key
  type __sk_buff (line 548) | struct __sk_buff
  type bpf_tunnel_key (line 548) | struct bpf_tunnel_key
  type __sk_buff (line 636) | struct __sk_buff
  type __sk_buff (line 805) | struct __sk_buff
  type __sk_buff (line 819) | struct __sk_buff
  type __sk_buff (line 850) | struct __sk_buff
  type __sk_buff (line 881) | struct __sk_buff
  type __sk_buff (line 896) | struct __sk_buff
  type __sk_buff (line 916) | struct __sk_buff
  type __sk_buff (line 992) | struct __sk_buff
  type __sk_buff (line 1032) | struct __sk_buff
  type __sk_buff (line 1048) | struct __sk_buff
  type __sk_buff (line 1060) | struct __sk_buff
  type __sk_buff (line 1100) | struct __sk_buff
  type xdp_md (line 1119) | struct xdp_md
  type __sk_buff (line 1166) | struct __sk_buff
  type __sk_buff (line 1177) | struct __sk_buff
  type __sk_buff (line 1266) | struct __sk_buff
  type __sk_buff (line 1310) | struct __sk_buff
  type bpf_sock_ops (line 1333) | struct bpf_sock_ops
  type xdp_md (line 1366) | struct xdp_md
  type bpf_perf_event_value (line 1420) | struct bpf_perf_event_value
  type bpf_perf_event_data (line 1435) | struct bpf_perf_event_data
  type bpf_perf_event_value (line 1435) | struct bpf_perf_event_value
  type pt_regs (line 1493) | struct pt_regs
  type bpf_sock_ops (line 1541) | struct bpf_sock_ops
  type sk_msg_md (line 1559) | struct sk_msg_md
  type sk_msg_md (line 1597) | struct sk_msg_md
  type sk_msg_md (line 1619) | struct sk_msg_md
  type sk_msg_md (line 1654) | struct sk_msg_md
  type bpf_sock_addr (line 1676) | struct bpf_sock_addr
  type sockaddr (line 1676) | struct sockaddr
  type xdp_md (line 1694) | struct xdp_md
  type __sk_buff (line 1714) | struct __sk_buff
  type bpf_xfrm_state (line 1714) | struct bpf_xfrm_state
  type bpf_fib_lookup (line 1815) | struct bpf_fib_lookup
  type bpf_sock_ops (line 1838) | struct bpf_sock_ops
  type sk_msg_md (line 1856) | struct sk_msg_md
  type __sk_buff (line 1874) | struct __sk_buff
  type __sk_buff (line 1915) | struct __sk_buff
  type __sk_buff (line 1934) | struct __sk_buff
  type __sk_buff (line 1954) | struct __sk_buff
  type __sk_buff (line 1987) | struct __sk_buff
  type __sk_buff (line 2060) | struct __sk_buff
  type sk_reuseport_md (line 2105) | struct sk_reuseport_md
  type __sk_buff (line 2127) | struct __sk_buff
  type bpf_sock (line 2168) | struct bpf_sock
  type bpf_sock_tuple (line 2168) | struct bpf_sock_tuple
  type bpf_sock (line 2209) | struct bpf_sock
  type bpf_sock_tuple (line 2209) | struct bpf_sock_tuple
  type sk_msg_md (line 2275) | struct sk_msg_md
  type sk_msg_md (line 2291) | struct sk_msg_md
  type bpf_spin_lock (line 2361) | struct bpf_spin_lock
  type bpf_spin_lock (line 2372) | struct bpf_spin_lock
  type bpf_sock (line 2384) | struct bpf_sock
  type bpf_sock (line 2384) | struct bpf_sock
  type bpf_tcp_sock (line 2396) | struct bpf_tcp_sock
  type bpf_sock (line 2396) | struct bpf_sock
  type __sk_buff (line 2410) | struct __sk_buff
  type bpf_sock (line 2422) | struct bpf_sock
  type bpf_sock (line 2422) | struct bpf_sock
  type bpf_sock (line 2445) | struct bpf_sock
  type bpf_sock_tuple (line 2445) | struct bpf_sock_tuple
  type tcphdr (line 2464) | struct tcphdr
  type bpf_sysctl (line 2484) | struct bpf_sysctl
  type bpf_sysctl (line 2507) | struct bpf_sysctl
  type bpf_sysctl (line 2528) | struct bpf_sysctl
  type bpf_sysctl (line 2549) | struct bpf_sysctl
  type tcphdr (line 2701) | struct tcphdr
  type bpf_perf_event_data (line 2873) | struct bpf_perf_event_data
  type bpf_pidns_info (line 2889) | struct bpf_pidns_info
  type seq_file (line 3036) | struct seq_file
  type seq_file (line 3050) | struct seq_file
  type __sk_buff (line 3216) | struct __sk_buff
  type tcp6_sock (line 3226) | struct tcp6_sock
  type tcp_sock (line 3236) | struct tcp_sock
  type tcp_timewait_sock (line 3246) | struct tcp_timewait_sock
  type tcp_request_sock (line 3256) | struct tcp_request_sock
  type udp6_sock (line 3266) | struct udp6_sock
  type task_struct (line 3302) | struct task_struct
  type bpf_sock_ops (line 3369) | struct bpf_sock_ops
  type bpf_sock_ops (line 3406) | struct bpf_sock_ops
  type bpf_sock_ops (line 3432) | struct bpf_sock_ops
  type path (line 3492) | struct path
  type btf_ptr (line 3543) | struct btf_ptr
  type seq_file (line 3555) | struct seq_file
  type btf_ptr (line 3555) | struct btf_ptr
  type __sk_buff (line 3568) | struct __sk_buff
  type bpf_redir_neigh (line 3593) | struct bpf_redir_neigh
  type task_struct (line 3682) | struct task_struct
  type task_struct (line 3694) | struct task_struct
  type task_struct (line 3706) | struct task_struct
  type linux_binprm (line 3720) | struct linux_binprm
  type inode (line 3748) | struct inode
  type socket (line 3760) | struct socket
  type file (line 3760) | struct file
  type bpf_timer (line 3946) | struct bpf_timer
  type bpf_timer (line 3961) | struct bpf_timer
  type bpf_timer (line 3991) | struct bpf_timer
  type bpf_timer (line 4005) | struct bpf_timer
  type task_struct (line 4044) | struct task_struct

FILE: include/libbpf/bpf_helpers.h
  function __always_inline (line 106) | static __always_inline void
  type bpf_map_def (line 138) | struct bpf_map_def {
  type libbpf_pin_type (line 146) | enum libbpf_pin_type {
  type libbpf_tristate (line 152) | enum libbpf_tristate {

FILE: include/libbpf/bpf_tracing.h
  type pt_regs (line 158) | struct pt_regs
  type pt_regs (line 210) | struct pt_regs
  type pt_regs (line 322) | struct pt_regs
  type pt_regs (line 450) | struct pt_regs

FILE: include/libbpf/btf.h
  type btf (line 22) | struct btf
  type btf_ext (line 23) | struct btf_ext
  type btf_type (line 24) | struct btf_type
  type bpf_object (line 26) | struct bpf_object
  type btf_endianness (line 28) | enum btf_endianness {
  type btf (line 33) | struct btf
  type btf (line 36) | struct btf
  type btf (line 38) | struct btf
  type btf_ext (line 40) | struct btf_ext
  type btf (line 41) | struct btf
  type btf_ext (line 42) | struct btf_ext
  type btf (line 43) | struct btf
  type btf (line 45) | struct btf
  type btf (line 48) | struct btf
  type btf (line 52) | struct btf
  type btf (line 53) | struct btf
  type bpf_object (line 55) | struct bpf_object
  type btf (line 55) | struct btf
  type btf (line 56) | struct btf
  type btf (line 57) | struct btf
  type btf (line 58) | struct btf
  type btf (line 60) | struct btf
  type btf (line 62) | struct btf
  type btf (line 63) | struct btf
  type btf (line 64) | struct btf
  type btf (line 66) | struct btf
  type btf (line 67) | struct btf
  type btf (line 68) | struct btf
  type btf (line 69) | struct btf
  type btf_endianness (line 69) | enum btf_endianness
  type btf (line 70) | struct btf
  type btf (line 71) | struct btf
  type btf (line 72) | struct btf
  type btf (line 73) | struct btf
  type btf (line 74) | struct btf
  type btf (line 75) | struct btf
  type btf (line 76) | struct btf
  type btf (line 77) | struct btf
  type btf (line 78) | struct btf
  type btf_ext (line 84) | struct btf_ext
  type btf_ext (line 85) | struct btf_ext
  type btf (line 88) | struct btf
  type btf_ext (line 89) | struct btf_ext
  type btf (line 93) | struct btf
  type btf_ext (line 94) | struct btf_ext
  type btf_ext (line 97) | struct btf_ext
  type btf_ext (line 98) | struct btf_ext
  type btf (line 100) | struct btf
  type btf (line 101) | struct btf
  type btf (line 102) | struct btf
  type btf (line 102) | struct btf
  type btf_type (line 103) | struct btf_type
  type btf (line 105) | struct btf
  type btf (line 106) | struct btf
  type btf (line 107) | struct btf
  type btf (line 108) | struct btf
  type btf (line 111) | struct btf
  type btf (line 112) | struct btf
  type btf (line 113) | struct btf
  type btf (line 117) | struct btf
  type btf (line 118) | struct btf
  type btf_fwd_kind (line 120) | enum btf_fwd_kind {
  type btf (line 126) | struct btf
  type btf_fwd_kind (line 126) | enum btf_fwd_kind
  type btf (line 127) | struct btf
  type btf (line 128) | struct btf
  type btf (line 129) | struct btf
  type btf (line 130) | struct btf
  type btf (line 133) | struct btf
  type btf_func_linkage (line 134) | enum btf_func_linkage
  type btf (line 135) | struct btf
  type btf (line 136) | struct btf
  type btf (line 139) | struct btf
  type btf (line 140) | struct btf
  type btf (line 141) | struct btf
  type btf_dedup_opts (line 144) | struct btf_dedup_opts {
  type btf (line 149) | struct btf
  type btf_ext (line 149) | struct btf_ext
  type btf_dedup_opts (line 150) | struct btf_dedup_opts
  type btf_dump (line 152) | struct btf_dump
  type btf_dump_opts (line 154) | struct btf_dump_opts {
  type btf (line 160) | struct btf
  type btf_ext (line 161) | struct btf_ext
  type btf_dump_opts (line 162) | struct btf_dump_opts
  type btf_dump (line 164) | struct btf_dump
  type btf_dump (line 166) | struct btf_dump
  type btf_dump_emit_type_decl_opts (line 168) | struct btf_dump_emit_type_decl_opts {
  type btf_dump (line 190) | struct btf_dump
  type btf_dump_emit_type_decl_opts (line 191) | struct btf_dump_emit_type_decl_opts
  type btf_dump_type_data_opts (line 194) | struct btf_dump_type_data_opts {
  type btf_dump (line 208) | struct btf_dump
  type btf_dump_type_data_opts (line 210) | struct btf_dump_type_data_opts
  function __u16 (line 215) | static inline __u16 btf_kind(const struct btf_type *t)
  function __u16 (line 220) | static inline __u16 btf_vlen(const struct btf_type *t)
  function btf_kflag (line 225) | static inline bool btf_kflag(const struct btf_type *t)
  function btf_is_void (line 230) | static inline bool btf_is_void(const struct btf_type *t)
  function btf_is_int (line 235) | static inline bool btf_is_int(const struct btf_type *t)
  function btf_is_ptr (line 240) | static inline bool btf_is_ptr(const struct btf_type *t)
  function btf_is_array (line 245) | static inline bool btf_is_array(const struct btf_type *t)
  function btf_is_struct (line 250) | static inline bool btf_is_struct(const struct btf_type *t)
  function btf_is_union (line 255) | static inline bool btf_is_union(const struct btf_type *t)
  function btf_is_composite (line 260) | static inline bool btf_is_composite(const struct btf_type *t)
  function btf_is_enum (line 267) | static inline bool btf_is_enum(const struct btf_type *t)
  function btf_is_fwd (line 272) | static inline bool btf_is_fwd(const struct btf_type *t)
  function btf_is_typedef (line 277) | static inline bool btf_is_typedef(const struct btf_type *t)
  function btf_is_volatile (line 282) | static inline bool btf_is_volatile(const struct btf_type *t)
  function btf_is_const (line 287) | static inline bool btf_is_const(const struct btf_type *t)
  function btf_is_restrict (line 292) | static inline bool btf_is_restrict(const struct btf_type *t)
  function btf_is_mod (line 297) | static inline bool btf_is_mod(const struct btf_type *t)
  function btf_is_func (line 306) | static inline bool btf_is_func(const struct btf_type *t)
  function btf_is_func_proto (line 311) | static inline bool btf_is_func_proto(const struct btf_type *t)
  function btf_is_var (line 316) | static inline bool btf_is_var(const struct btf_type *t)
  function btf_is_datasec (line 321) | static inline bool btf_is_datasec(const struct btf_type *t)
  function btf_is_float (line 326) | static inline bool btf_is_float(const struct btf_type *t)
  function __u8 (line 331) | static inline __u8 btf_int_encoding(const struct btf_type *t)
  function __u8 (line 336) | static inline __u8 btf_int_offset(const struct btf_type *t)
  function __u8 (line 341) | static inline __u8 btf_int_bits(const struct btf_type *t)
  type btf_array (line 346) | struct btf_array
  type btf_type (line 346) | struct btf_type
  type btf_array (line 348) | struct btf_array
  type btf_enum (line 351) | struct btf_enum
  type btf_type (line 351) | struct btf_type
  type btf_enum (line 353) | struct btf_enum
  type btf_member (line 356) | struct btf_member
  type btf_type (line 356) | struct btf_type
  type btf_member (line 358) | struct btf_member
  function __u32 (line 362) | static inline __u32 btf_member_bit_offset(const struct btf_type *t,
  function __u32 (line 374) | static inline __u32 btf_member_bitfield_size(const struct btf_type *t,
  type btf_param (line 383) | struct btf_param
  type btf_type (line 383) | struct btf_type
  type btf_param (line 385) | struct btf_param
  type btf_var (line 388) | struct btf_var
  type btf_type (line 388) | struct btf_type
  type btf_var (line 390) | struct btf_var
  type btf_var_secinfo (line 393) | struct btf_var_secinfo
  type btf_type (line 394) | struct btf_type
  type btf_var_secinfo (line 396) | struct btf_var_secinfo

FILE: include/libbpf/libbpf.h
  type libbpf_errno (line 27) | enum libbpf_errno {
  type libbpf_print_level (line 50) | enum libbpf_print_level {
  type libbpf_print_level (line 56) | enum libbpf_print_level
  type bpf_object (line 62) | struct bpf_object
  type bpf_object_open_attr (line 64) | struct bpf_object_open_attr {
  type bpf_object_open_opts (line 69) | struct bpf_object_open_opts {
  type bpf_object_open_opts (line 109) | struct bpf_object_open_opts
  type bpf_object_open_opts (line 112) | struct bpf_object_open_opts
  type bpf_object_open_attr (line 119) | struct bpf_object_open_attr
  type libbpf_pin_type (line 121) | enum libbpf_pin_type {
  type bpf_object (line 131) | struct bpf_object
  type bpf_object (line 132) | struct bpf_object
  type bpf_object (line 134) | struct bpf_object
  type bpf_object (line 136) | struct bpf_object
  type bpf_object (line 138) | struct bpf_object
  type bpf_object (line 139) | struct bpf_object
  type bpf_object_load_attr (line 141) | struct bpf_object_load_attr {
  type bpf_object (line 148) | struct bpf_object
  type bpf_object_load_attr (line 149) | struct bpf_object_load_attr
  type bpf_object (line 150) | struct bpf_object
  type bpf_object (line 152) | struct bpf_object
  type bpf_object (line 153) | struct bpf_object
  type bpf_object (line 154) | struct bpf_object
  type btf (line 156) | struct btf
  type bpf_object (line 157) | struct bpf_object
  type bpf_object (line 158) | struct bpf_object
  type bpf_object (line 161) | struct bpf_object
  type bpf_object (line 164) | struct bpf_object
  type bpf_object (line 167) | struct bpf_object
  type bpf_object (line 174) | struct bpf_object
  type bpf_object (line 175) | struct bpf_object
  type bpf_object (line 177) | struct bpf_object
  type bpf_prog_type (line 180) | enum bpf_prog_type
  type bpf_attach_type (line 181) | enum bpf_attach_type
  type bpf_attach_type (line 183) | enum bpf_attach_type
  type bpf_attach_type (line 185) | enum bpf_attach_type
  type bpf_program (line 188) | struct bpf_program
  type bpf_program (line 189) | struct bpf_program
  type bpf_object (line 190) | struct bpf_object
  type bpf_program (line 197) | struct bpf_program
  type bpf_object (line 198) | struct bpf_object
  type bpf_program (line 200) | struct bpf_program
  type bpf_program (line 202) | struct bpf_program
  type bpf_program (line 205) | struct bpf_program
  type bpf_program (line 206) | struct bpf_program
  type bpf_program (line 209) | struct bpf_program
  type bpf_program (line 210) | struct bpf_program
  type bpf_program (line 212) | struct bpf_program
  type bpf_program (line 213) | struct bpf_program
  type bpf_program (line 214) | struct bpf_program
  type bpf_program (line 217) | struct bpf_program
  type bpf_program (line 219) | struct bpf_program
  type bpf_program (line 221) | struct bpf_program
  type bpf_program (line 222) | struct bpf_program
  type bpf_program (line 225) | struct bpf_program
  type bpf_program (line 228) | struct bpf_program
  type bpf_program (line 229) | struct bpf_program
  type bpf_program (line 230) | struct bpf_program
  type bpf_link (line 232) | struct bpf_link
  type bpf_link (line 235) | struct bpf_link
  type bpf_link (line 236) | struct bpf_link
  type bpf_link (line 237) | struct bpf_link
  type bpf_link (line 238) | struct bpf_link
  type bpf_link (line 239) | struct bpf_link
  type bpf_program (line 240) | struct bpf_program
  type bpf_link (line 241) | struct bpf_link
  type bpf_link (line 242) | struct bpf_link
  type bpf_link (line 243) | struct bpf_link
  type bpf_program (line 246) | struct bpf_program
  type bpf_perf_event_opts (line 248) | struct bpf_perf_event_opts {
  type bpf_program (line 257) | struct bpf_program
  type bpf_program (line 260) | struct bpf_program
  type bpf_perf_event_opts (line 261) | struct bpf_perf_event_opts
  type bpf_kprobe_opts (line 263) | struct bpf_kprobe_opts {
  type bpf_program (line 277) | struct bpf_program
  type bpf_program (line 280) | struct bpf_program
  type bpf_kprobe_opts (line 282) | struct bpf_kprobe_opts
  type bpf_uprobe_opts (line 284) | struct bpf_uprobe_opts {
  type bpf_program (line 300) | struct bpf_program
  type bpf_program (line 304) | struct bpf_program
  type bpf_uprobe_opts (line 306) | struct bpf_uprobe_opts
  type bpf_tracepoint_opts (line 308) | struct bpf_tracepoint_opts {
  type bpf_program (line 317) | struct bpf_program
  type bpf_program (line 321) | struct bpf_program
  type bpf_tracepoint_opts (line 324) | struct bpf_tracepoint_opts
  type bpf_program (line 327) | struct bpf_program
  type bpf_program (line 330) | struct bpf_program
  type bpf_program (line 332) | struct bpf_program
  type bpf_program (line 334) | struct bpf_program
  type bpf_program (line 336) | struct bpf_program
  type bpf_program (line 338) | struct bpf_program
  type bpf_program (line 340) | struct bpf_program
  type bpf_map (line 343) | struct bpf_map
  type bpf_map (line 345) | struct bpf_map
  type bpf_iter_attach_opts (line 347) | struct bpf_iter_attach_opts {
  type bpf_program (line 355) | struct bpf_program
  type bpf_iter_attach_opts (line 356) | struct bpf_iter_attach_opts
  type bpf_insn (line 358) | struct bpf_insn
  type bpf_prog_prep_result (line 389) | struct bpf_prog_prep_result {
  type bpf_program (line 413) | struct bpf_program
  type bpf_insn (line 414) | struct bpf_insn
  type bpf_prog_prep_result (line 415) | struct bpf_prog_prep_result
  type bpf_program (line 417) | struct bpf_program
  type bpf_program (line 420) | struct bpf_program
  type bpf_program (line 425) | struct bpf_program
  type bpf_program (line 426) | struct bpf_program
  type bpf_program (line 427) | struct bpf_program
  type bpf_program (line 428) | struct bpf_program
  type bpf_program (line 429) | struct bpf_program
  type bpf_program (line 430) | struct bpf_program
  type bpf_program (line 431) | struct bpf_program
  type bpf_program (line 432) | struct bpf_program
  type bpf_program (line 433) | struct bpf_program
  type bpf_program (line 434) | struct bpf_program
  type bpf_program (line 435) | struct bpf_program
  type bpf_program (line 436) | struct bpf_program
  type bpf_program (line 437) | struct bpf_program
  type bpf_program (line 439) | struct bpf_program
  type bpf_program (line 440) | struct bpf_program
  type bpf_prog_type (line 441) | enum bpf_prog_type
  type bpf_program (line 444) | struct bpf_program
  type bpf_program (line 446) | struct bpf_program
  type bpf_attach_type (line 447) | enum bpf_attach_type
  type bpf_program (line 450) | struct bpf_program
  type bpf_program (line 453) | struct bpf_program
  type bpf_program (line 454) | struct bpf_program
  type bpf_program (line 455) | struct bpf_program
  type bpf_program (line 456) | struct bpf_program
  type bpf_program (line 457) | struct bpf_program
  type bpf_program (line 458) | struct bpf_program
  type bpf_program (line 459) | struct bpf_program
  type bpf_program (line 460) | struct bpf_program
  type bpf_program (line 461) | struct bpf_program
  type bpf_program (line 462) | struct bpf_program
  type bpf_program (line 463) | struct bpf_program
  type bpf_program (line 464) | struct bpf_program
  type bpf_program (line 465) | struct bpf_program
  type bpf_map_def (line 473) | struct bpf_map_def {
  type bpf_object (line 486) | struct bpf_object
  type bpf_object (line 489) | struct bpf_object
  type bpf_object (line 496) | struct bpf_object
  type bpf_map (line 499) | struct bpf_map
  type bpf_object (line 499) | struct bpf_object
  type bpf_map (line 507) | struct bpf_map
  type bpf_object (line 507) | struct bpf_object
  type bpf_map (line 510) | struct bpf_map
  type bpf_map (line 511) | struct bpf_map
  type bpf_map (line 513) | struct bpf_map
  type bpf_map (line 515) | struct bpf_map
  type bpf_map (line 517) | struct bpf_map
  type bpf_map (line 518) | struct bpf_map
  type bpf_map_type (line 518) | enum bpf_map_type
  type bpf_map (line 520) | struct bpf_map
  type bpf_map (line 521) | struct bpf_map
  type bpf_map (line 522) | struct bpf_map
  type bpf_map (line 524) | struct bpf_map
  type bpf_map (line 525) | struct bpf_map
  type bpf_map (line 527) | struct bpf_map
  type bpf_map (line 528) | struct bpf_map
  type bpf_map (line 530) | struct bpf_map
  type bpf_map (line 531) | struct bpf_map
  type bpf_map (line 533) | struct bpf_map
  type bpf_map (line 534) | struct bpf_map
  type bpf_map (line 536) | struct bpf_map
  type bpf_map (line 537) | struct bpf_map
  type bpf_map (line 539) | struct bpf_map
  type bpf_map (line 540) | struct bpf_map
  type bpf_map (line 542) | struct bpf_map
  type bpf_map (line 543) | struct bpf_map
  type bpf_map (line 545) | struct bpf_map
  type bpf_map (line 546) | struct bpf_map
  type bpf_map (line 548) | struct bpf_map
  type bpf_map (line 549) | struct bpf_map
  type bpf_map (line 550) | struct bpf_map
  type bpf_map (line 551) | struct bpf_map
  type bpf_map (line 552) | struct bpf_map
  type bpf_map (line 553) | struct bpf_map
  type bpf_map (line 554) | struct bpf_map
  type bpf_map (line 555) | struct bpf_map
  type bpf_map (line 556) | struct bpf_map
  type bpf_map (line 558) | struct bpf_map
  type bpf_map (line 559) | struct bpf_map
  type bpf_prog_load_attr (line 563) | struct bpf_prog_load_attr {
  type bpf_prog_load_attr (line 572) | struct bpf_prog_load_attr
  type bpf_object (line 573) | struct bpf_object
  type bpf_prog_type (line 574) | enum bpf_prog_type
  type bpf_object (line 575) | struct bpf_object
  type xdp_link_info (line 578) | struct xdp_link_info {
  type bpf_xdp_set_link_opts (line 586) | struct bpf_xdp_set_link_opts {
  type bpf_xdp_set_link_opts (line 595) | struct bpf_xdp_set_link_opts
  type xdp_link_info (line 597) | struct xdp_link_info
  type bpf_tc_attach_point (line 601) | enum bpf_tc_attach_point {
  type bpf_tc_flags (line 610) | enum bpf_tc_flags {
  type bpf_tc_hook (line 614) | struct bpf_tc_hook {
  type bpf_tc_opts (line 623) | struct bpf_tc_opts {
  type bpf_tc_hook (line 634) | struct bpf_tc_hook
  type bpf_tc_hook (line 635) | struct bpf_tc_hook
  type bpf_tc_hook (line 636) | struct bpf_tc_hook
  type bpf_tc_opts (line 637) | struct bpf_tc_opts
  type bpf_tc_hook (line 638) | struct bpf_tc_hook
  type bpf_tc_opts (line 639) | struct bpf_tc_opts
  type bpf_tc_hook (line 640) | struct bpf_tc_hook
  type bpf_tc_opts (line 641) | struct bpf_tc_opts
  type ring_buffer (line 644) | struct ring_buffer
  type ring_buffer_opts (line 648) | struct ring_buffer_opts {
  type ring_buffer_opts (line 656) | struct ring_buffer_opts
  type ring_buffer (line 657) | struct ring_buffer
  type ring_buffer (line 658) | struct ring_buffer
  type ring_buffer (line 660) | struct ring_buffer
  type ring_buffer (line 661) | struct ring_buffer
  type ring_buffer (line 662) | struct ring_buffer
  type perf_buffer (line 665) | struct perf_buffer
  type perf_buffer_opts (line 672) | struct perf_buffer_opts {
  type perf_buffer_opts (line 683) | struct perf_buffer_opts
  type bpf_perf_event_ret (line 685) | enum bpf_perf_event_ret {
  type perf_event_header (line 691) | struct perf_event_header
  type bpf_perf_event_ret (line 693) | enum bpf_perf_event_ret
  type perf_event_header (line 694) | struct perf_event_header
  type perf_buffer_raw_opts (line 697) | struct perf_buffer_raw_opts {
  type perf_buffer_raw_opts (line 716) | struct perf_buffer_raw_opts
  type perf_buffer (line 718) | struct perf_buffer
  type perf_buffer (line 719) | struct perf_buffer
  type perf_buffer (line 720) | struct perf_buffer
  type perf_buffer (line 721) | struct perf_buffer
  type perf_buffer (line 722) | struct perf_buffer
  type perf_buffer (line 723) | struct perf_buffer
  type perf_buffer (line 724) | struct perf_buffer
  type bpf_perf_event_ret (line 726) | enum bpf_perf_event_ret
  type perf_event_header (line 727) | struct perf_event_header
  type bpf_prog_linfo (line 734) | struct bpf_prog_linfo
  type bpf_prog_info (line 735) | struct bpf_prog_info
  type bpf_prog_linfo (line 737) | struct bpf_prog_linfo
  type bpf_prog_info (line 739) | struct bpf_prog_info
  type bpf_prog_linfo (line 741) | struct bpf_prog_linfo
  type bpf_prog_linfo (line 744) | struct bpf_prog_linfo
  type bpf_prog_type (line 755) | enum bpf_prog_type
  type bpf_map_type (line 757) | enum bpf_map_type
  type bpf_func_id (line 758) | enum bpf_func_id
  type bpf_prog_type (line 759) | enum bpf_prog_type
  type bpf_prog_info_array (line 791) | enum bpf_prog_info_array {
  type bpf_prog_info_linear (line 805) | struct bpf_prog_info_linear {
  type bpf_prog_info_linear (line 820) | struct bpf_prog_info_linear
  type bpf_prog_info_linear (line 823) | struct bpf_prog_info_linear
  type bpf_map_skeleton (line 841) | struct bpf_map_skeleton {
  type bpf_prog_skeleton (line 847) | struct bpf_prog_skeleton {
  type bpf_object_skeleton (line 853) | struct bpf_object_skeleton {
  type bpf_object_skeleton (line 872) | struct bpf_object_skeleton
  type bpf_object_open_opts (line 873) | struct bpf_object_open_opts
  type bpf_object_skeleton (line 874) | struct bpf_object_skeleton
  type bpf_object_skeleton (line 875) | struct bpf_object_skeleton
  type bpf_object_skeleton (line 876) | struct bpf_object_skeleton
  type bpf_object_skeleton (line 877) | struct bpf_object_skeleton
  type gen_loader_opts (line 879) | struct gen_loader_opts {
  type bpf_object (line 888) | struct bpf_object
  type gen_loader_opts (line 889) | struct gen_loader_opts
  type libbpf_tristate (line 891) | enum libbpf_tristate {
  type bpf_linker_opts (line 897) | struct bpf_linker_opts {
  type bpf_linker_file_opts (line 903) | struct bpf_linker_file_opts {
  type bpf_linker (line 909) | struct bpf_linker
  type bpf_linker_opts (line 911) | struct bpf_linker_opts
  type bpf_linker (line 912) | struct bpf_linker
  type bpf_linker_file_opts (line 914) | struct bpf_linker_file_opts
  type bpf_linker (line 915) | struct bpf_linker
  type bpf_linker (line 916) | struct bpf_linker

FILE: include/libbpf/libbpf_legacy.h
  type libbpf_strict_mode (line 23) | enum libbpf_strict_mode {
  type libbpf_strict_mode (line 52) | enum libbpf_strict_mode

FILE: include/libbpf/skel_internal.h
  type bpf_map_desc (line 17) | struct bpf_map_desc {
  type bpf_prog_desc (line 30) | struct bpf_prog_desc {
  type bpf_loader_ctx (line 34) | struct bpf_loader_ctx {
  type bpf_load_and_run_opts (line 41) | struct bpf_load_and_run_opts {
  function skel_sys_bpf (line 50) | static inline int skel_sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
  function skel_closenz (line 56) | static inline int skel_closenz(int fd)
  function bpf_load_and_run (line 63) | static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)

FILE: include/libbpf/xsk.h
  type xsk_umem (line 111) | struct xsk_umem
  type xsk_socket (line 112) | struct xsk_socket
  function __u64 (line 114) | static inline __u64 *xsk_ring_prod__fill_addr(struct xsk_ring_prod *fill,
  function __u64 (line 122) | static inline const __u64 *
  type xdp_desc (line 130) | struct xdp_desc
  type xsk_ring_prod (line 130) | struct xsk_ring_prod
  type xdp_desc (line 133) | struct xdp_desc
  type xdp_desc (line 133) | struct xdp_desc
  type xdp_desc (line 138) | struct xdp_desc
  type xsk_ring_cons (line 139) | struct xsk_ring_cons
  type xdp_desc (line 141) | struct xdp_desc
  type xdp_desc (line 141) | struct xdp_desc
  function xsk_ring_prod__needs_wakeup (line 146) | static inline int xsk_ring_prod__needs_wakeup(const struct xsk_ring_prod...
  function __u32 (line 151) | static inline __u32 xsk_prod_nb_free(struct xsk_ring_prod *r, __u32 nb)
  function __u32 (line 171) | static inline __u32 xsk_cons_nb_avail(struct xsk_ring_cons *r, __u32 nb)
  function __u32 (line 183) | static inline __u32 xsk_ring_prod__reserve(struct xsk_ring_prod *prod, _...
  function xsk_ring_prod__submit (line 194) | static inline void xsk_ring_prod__submit(struct xsk_ring_prod *prod, __u...
  function __u32 (line 202) | static inline __u32 xsk_ring_cons__peek(struct xsk_ring_cons *cons, __u3...
  function xsk_ring_cons__cancel (line 214) | static inline void xsk_ring_cons__cancel(struct xsk_ring_cons *cons, __u...
  function xsk_ring_cons__release (line 219) | static inline void xsk_ring_cons__release(struct xsk_ring_cons *cons, __...
  function __u64 (line 233) | static inline __u64 xsk_umem__extract_addr(__u64 addr)
  function __u64 (line 238) | static inline __u64 xsk_umem__extract_offset(__u64 addr)
  function __u64 (line 243) | static inline __u64 xsk_umem__add_offset_to_addr(__u64 addr)
  type xsk_umem (line 248) | struct xsk_umem
  type xsk_socket (line 249) | struct xsk_socket
  type xsk_umem_config (line 258) | struct xsk_umem_config {
  type xsk_socket (line 268) | struct xsk_socket
  type xsk_socket_config (line 274) | struct xsk_socket_config {
  type xsk_umem (line 283) | struct xsk_umem
  type xsk_ring_prod (line 285) | struct xsk_ring_prod
  type xsk_ring_cons (line 286) | struct xsk_ring_cons
  type xsk_umem_config (line 287) | struct xsk_umem_config
  type xsk_umem (line 288) | struct xsk_umem
  type xsk_ring_prod (line 290) | struct xsk_ring_prod
  type xsk_ring_cons (line 291) | struct xsk_ring_cons
  type xsk_umem_config (line 292) | struct xsk_umem_config
  type xsk_umem (line 293) | struct xsk_umem
  type xsk_ring_prod (line 295) | struct xsk_ring_prod
  type xsk_ring_cons (line 296) | struct xsk_ring_cons
  type xsk_umem_config (line 297) | struct xsk_umem_config
  type xsk_socket (line 298) | struct xsk_socket
  type xsk_umem (line 300) | struct xsk_umem
  type xsk_ring_cons (line 301) | struct xsk_ring_cons
  type xsk_ring_prod (line 302) | struct xsk_ring_prod
  type xsk_socket_config (line 303) | struct xsk_socket_config
  type xsk_socket (line 305) | struct xsk_socket
  type xsk_umem (line 307) | struct xsk_umem
  type xsk_ring_cons (line 308) | struct xsk_ring_cons
  type xsk_ring_prod (line 309) | struct xsk_ring_prod
  type xsk_ring_prod (line 310) | struct xsk_ring_prod
  type xsk_ring_cons (line 311) | struct xsk_ring_cons
  type xsk_socket_config (line 312) | struct xsk_socket_config
  type xsk_umem (line 315) | struct xsk_umem
  type xsk_socket (line 316) | struct xsk_socket

FILE: include/span_context.h
  type span_context (line 6) | struct span_context {
  type span_context (line 14) | struct span_context
  function span_context (line 19) | span_context generate_span_context() {
  function __always_inline (line 26) | static __always_inline void span_context_to_w3c_string(struct span_conte...
  function __always_inline (line 50) | static __always_inline void w3c_string_to_span_context(char *str, struct...

FILE: include/utils.h
  function __always_inline (line 8) | static __always_inline bool bpf_memcmp(char* s1, char* s2, s32 size) {
  function __always_inline (line 18) | static __always_inline void generate_random_bytes(unsigned char* buff, u...
  function __always_inline (line 29) | static __always_inline void bytes_to_hex_string(unsigned char* pin, u32 ...
  function __always_inline (line 38) | static __always_inline void hex_string_to_bytes(char* str, u32 size, uns...
  function __always_inline (line 48) | static __always_inline void copy_byte_arrays(unsigned char *src, unsigne...

FILE: pkg/inject/data.go
  type TrackedOffsets (line 3) | type TrackedOffsets struct
  type TrackedLibrary (line 7) | type TrackedLibrary struct
  type TrackedDataMember (line 12) | type TrackedDataMember struct
  type VersionedOffset (line 18) | type VersionedOffset struct

FILE: pkg/inject/injector.go
  type Injector (line 17) | type Injector struct
    method Inject (line 49) | func (i *Injector) Inject(loadBpf loadBpfFunc, library string, libVers...
    method addCommonInjections (line 78) | func (i *Injector) addCommonInjections(varsMap map[string]interface{},...
    method getFieldOffset (line 87) | func (i *Injector) getFieldOffset(libName string, libVersion string, s...
  function New (line 25) | func New(target *process.TargetDetails) (*Injector, error) {
  type loadBpfFunc (line 41) | type loadBpfFunc
  type InjectStructField (line 43) | type InjectStructField struct

FILE: pkg/instrumentors/allocator/allocator_linux.go
  type Allocator (line 11) | type Allocator struct
    method Load (line 17) | func (a *Allocator) Load(ctx *context.InstrumentorContext) error {
    method mountBpfFS (line 30) | func (a *Allocator) mountBpfFS() error {
  function New (line 13) | func New() *Allocator {

FILE: pkg/instrumentors/api.go
  type Instrumentor (line 8) | type Instrumentor interface

FILE: pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c
  type http_request_t (line 10) | struct http_request_t {
  type http_request_t (line 21) | struct http_request_t
  function uprobe_GorillaMux_ServeHTTP (line 38) | int uprobe_GorillaMux_ServeHTTP(struct pt_regs *ctx) {
  function uprobe_GorillaMux_ServeHTTP_Returns (line 78) | int uprobe_GorillaMux_ServeHTTP_Returns(struct pt_regs *ctx) {

FILE: pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go
  type HttpEvent (line 25) | type HttpEvent struct
  type gorillaMuxInstrumentor (line 33) | type gorillaMuxInstrumentor struct
    method LibraryName (line 44) | func (g *gorillaMuxInstrumentor) LibraryName() string {
    method FuncNames (line 48) | func (g *gorillaMuxInstrumentor) FuncNames() []string {
    method Load (line 52) | func (g *gorillaMuxInstrumentor) Load(ctx *context.InstrumentorContext...
    method Run (line 127) | func (g *gorillaMuxInstrumentor) Run(eventsChan chan<- *events.Event) {
    method convertEvent (line 154) | func (g *gorillaMuxInstrumentor) convertEvent(e *HttpEvent) *events.Ev...
    method Close (line 178) | func (g *gorillaMuxInstrumentor) Close() {
  function New (line 40) | func New() *gorillaMuxInstrumentor {

FILE: pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c
  type grpc_request_t (line 12) | struct grpc_request_t {
  type hpack_header_field (line 21) | struct hpack_header_field {
  type grpc_request_t (line 30) | struct grpc_request_t
  type headers_buff (line 34) | struct headers_buff {
  type headers_buff (line 41) | struct headers_buff
  function uprobe_ClientConn_Invoke (line 55) | int uprobe_ClientConn_Invoke(struct pt_regs *ctx) {
  function uprobe_ClientConn_Invoke_Returns (line 89) | int uprobe_ClientConn_Invoke_Returns(struct pt_regs *ctx) {
  function uprobe_Http2Client_CreateHeaderFields (line 105) | int uprobe_Http2Client_CreateHeaderFields(struct pt_regs *ctx) {

FILE: pkg/instrumentors/bpf/google/golang/org/grpc/probe.go
  type GrpcEvent (line 26) | type GrpcEvent struct
  type grpcInstrumentor (line 35) | type grpcInstrumentor struct
    method LibraryName (line 47) | func (g *grpcInstrumentor) LibraryName() string {
    method FuncNames (line 51) | func (g *grpcInstrumentor) FuncNames() []string {
    method Load (line 56) | func (g *grpcInstrumentor) Load(ctx *context.InstrumentorContext) error {
    method Run (line 136) | func (g *grpcInstrumentor) Run(eventsChan chan<- *events.Event) {
    method convertEvent (line 164) | func (g *grpcInstrumentor) convertEvent(e *GrpcEvent) *events.Event {
    method Close (line 212) | func (g *grpcInstrumentor) Close() {
  function New (line 43) | func New() *grpcInstrumentor {

FILE: pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c
  type grpc_request_t (line 14) | struct grpc_request_t {
  type grpc_request_t (line 25) | struct grpc_request_t
  type grpc_request_t (line 32) | struct grpc_request_t
  type hpack_header_field (line 40) | struct hpack_header_field {
  function uprobe_server_handleStream (line 56) | int uprobe_server_handleStream(struct pt_regs *ctx) {
  function uprobe_server_handleStream_Returns (line 95) | int uprobe_server_handleStream_Returns(struct pt_regs *ctx) {
  function uprobe_decodeState_decodeHeader (line 116) | int uprobe_decodeState_decodeHeader(struct pt_regs *ctx) {

FILE: pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go
  type GrpcEvent (line 25) | type GrpcEvent struct
  type grpcServerInstrumentor (line 33) | type grpcServerInstrumentor struct
    method LibraryName (line 45) | func (g *grpcServerInstrumentor) LibraryName() string {
    method FuncNames (line 49) | func (g *grpcServerInstrumentor) FuncNames() []string {
    method Load (line 54) | func (g *grpcServerInstrumentor) Load(ctx *context.InstrumentorContext...
    method Run (line 151) | func (g *grpcServerInstrumentor) Run(eventsChan chan<- *events.Event) {
    method convertEvent (line 178) | func (g *grpcServerInstrumentor) convertEvent(e *GrpcEvent) *events.Ev...
    method Close (line 215) | func (g *grpcServerInstrumentor) Close() {
  function New (line 41) | func New() *grpcServerInstrumentor {

FILE: pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c
  type http_request_t (line 10) | struct http_request_t {
  type http_request_t (line 21) | struct http_request_t
  function uprobe_ServerMux_ServeHTTP (line 38) | int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) {
  function uprobe_ServerMux_ServeHTTP_Returns (line 78) | int uprobe_ServerMux_ServeHTTP_Returns(struct pt_regs *ctx) {

FILE: pkg/instrumentors/bpf/net/http/server/probe.go
  type HttpEvent (line 25) | type HttpEvent struct
  type httpServerInstrumentor (line 33) | type httpServerInstrumentor struct
    method LibraryName (line 44) | func (h *httpServerInstrumentor) LibraryName() string {
    method FuncNames (line 48) | func (h *httpServerInstrumentor) FuncNames() []string {
    method Load (line 52) | func (h *httpServerInstrumentor) Load(ctx *context.InstrumentorContext...
    method Run (line 127) | func (h *httpServerInstrumentor) Run(eventsChan chan<- *events.Event) {
    method convertEvent (line 154) | func (h *httpServerInstrumentor) convertEvent(e *HttpEvent) *events.Ev...
    method Close (line 178) | func (h *httpServerInstrumentor) Close() {
  function New (line 40) | func New() *httpServerInstrumentor {

FILE: pkg/instrumentors/bpffs/bpfsfs.go
  constant BpfFsPath (line 4) | BpfFsPath = "/sys/fs/bpf"

FILE: pkg/instrumentors/context/inst_context.go
  type InstrumentorContext (line 9) | type InstrumentorContext struct

FILE: pkg/instrumentors/context/span_context.go
  type EbpfSpanContext (line 5) | type EbpfSpanContext struct

FILE: pkg/instrumentors/events/event.go
  type Event (line 8) | type Event struct

FILE: pkg/instrumentors/manager.go
  type instrumentorsManager (line 20) | type instrumentorsManager struct
    method registerInstrumentor (line 45) | func (m *instrumentorsManager) registerInstrumentor(instrumentor Instr...
    method GetRelevantFuncs (line 54) | func (m *instrumentorsManager) GetRelevantFuncs() map[string]interface...
    method FilterUnusedInstrumentors (line 65) | func (m *instrumentorsManager) FilterUnusedInstrumentors(target *proce...
  function NewManager (line 28) | func NewManager(otelController *opentelemetry.Controller) (*instrumentor...
  function registerInstrumentors (line 88) | func registerInstrumentors(m *instrumentorsManager) error {

FILE: pkg/instrumentors/runner.go
  method Run (line 13) | func (m *instrumentorsManager) Run(target *process.TargetDetails) error {
  method load (line 40) | func (m *instrumentorsManager) load(target *process.TargetDetails) error {
  method cleanup (line 81) | func (m *instrumentorsManager) cleanup() {
  method Close (line 88) | func (m *instrumentorsManager) Close() {

FILE: pkg/log/logger.go
  function Init (line 11) | func Init() error {

FILE: pkg/opentelemetry/controller.go
  constant otelEndpointEnvVar (line 24) | otelEndpointEnvVar    = "OTEL_EXPORTER_OTLP_ENDPOINT"
  constant otelServiceNameEnvVar (line 25) | otelServiceNameEnvVar = "OTEL_SERVICE_NAME"
  type Controller (line 28) | type Controller struct
    method getTracer (line 34) | func (c *Controller) getTracer(libName string) trace.Tracer {
    method Trace (line 45) | func (c *Controller) Trace(event *events.Event) {
    method convertTime (line 68) | func (c *Controller) convertTime(t int64) time.Time {
  function NewStdoutController (line 72) | func NewStdoutController() (*Controller, error) {
  function NewController (line 98) | func NewController() (*Controller, error) {
  function getBootTime (line 157) | func getBootTime() (*time.Time, error) {
  function getBootTimeSyscall (line 172) | func getBootTimeSyscall() (int64, error) {
  function estimateBootTimeOffset (line 183) | func estimateBootTimeOffset() (bootTimeOffset int64, err error) {

FILE: pkg/opentelemetry/id_generator.go
  type eBPFSourceIDGenerator (line 9) | type eBPFSourceIDGenerator struct
    method NewIDs (line 35) | func (e *eBPFSourceIDGenerator) NewIDs(ctx context.Context) (trace.Tra...
    method NewSpanID (line 44) | func (e *eBPFSourceIDGenerator) NewSpanID(ctx context.Context, traceID...
  type ebpfEventKey (line 11) | type ebpfEventKey struct
  function NewEbpfSourceIDGenerator (line 13) | func NewEbpfSourceIDGenerator() *eBPFSourceIDGenerator {
  function ContextWithEbpfEvent (line 17) | func ContextWithEbpfEvent(ctx context.Context, event events.Event) conte...
  function EventFromContext (line 21) | func EventFromContext(ctx context.Context) *events.Event {

FILE: pkg/process/analyze.go
  constant mapSize (line 14) | mapSize = 4096 * 6 * 1024
  type TargetDetails (line 17) | type TargetDetails struct
    method IsRegistersABI (line 36) | func (t *TargetDetails) IsRegistersABI() bool {
    method GetFunctionOffset (line 41) | func (t *TargetDetails) GetFunctionOffset(name string) (uint64, error) {
    method GetFunctionReturns (line 51) | func (t *TargetDetails) GetFunctionReturns(name string) ([]uint64, err...
  type AllocationDetails (line 25) | type AllocationDetails struct
  type Func (line 30) | type Func struct
  method remoteMmap (line 61) | func (a *processAnalyzer) remoteMmap(pid int, mapSize uint64) (uint64, e...
  method Analyze (line 85) | func (a *processAnalyzer) Analyze(pid int, relevantFuncs map[string]inte...
  function findFunctions (line 135) | func findFunctions(elfF *elf.File, relevantFuncs map[string]interface{})...

FILE: pkg/process/args.go
  constant ExePathEnvVar (line 10) | ExePathEnvVar = "OTEL_TARGET_EXE"
  type TargetArgs (line 13) | type TargetArgs struct
    method Validate (line 18) | func (t *TargetArgs) Validate() error {
  function ParseTargetArgs (line 26) | func ParseTargetArgs() *TargetArgs {

FILE: pkg/process/discover.go
  constant initExeName (line 16) | initExeName = "/odigos/init"
  type processAnalyzer (line 19) | type processAnalyzer struct
    method DiscoverProcessID (line 31) | func (a *processAnalyzer) DiscoverProcessID(target *TargetArgs) (int, ...
    method findProcessID (line 53) | func (a *processAnalyzer) findProcessID(target *TargetArgs) (int, erro...
    method Close (line 103) | func (a *processAnalyzer) Close() {
  function NewAnalyzer (line 24) | func NewAnalyzer() *processAnalyzer {

FILE: pkg/process/funcs_nonstripped.go
  function FindFunctionsUnStripped (line 10) | func FindFunctionsUnStripped(elfF *elf.File, relevantFuncs map[string]in...
  function getFuncOffsetUnstripped (line 43) | func getFuncOffsetUnstripped(f *elf.File, symbol elf.Symbol) (uint64, er...
  function findFuncReturnsUnstripped (line 73) | func findFuncReturnsUnstripped(elfFile *elf.File, sym elf.Symbol, functi...

FILE: pkg/process/funcs_stripped.go
  function FindFunctionsStripped (line 10) | func FindFunctionsStripped(elfF *elf.File, relevantFuncs map[string]inte...
  function findFuncOffsetStripped (line 53) | func findFuncOffsetStripped(f *gosym.Func, elfF *elf.File) (uint64, []ui...

FILE: pkg/process/module.go
  method getModuleDetails (line 21) | func (a *processAnalyzer) getModuleDetails(f *elf.File) (*version.Versio...
  function parseGoVersion (line 37) | func parseGoVersion(vers string) (*version.Version, error) {
  function getGoDetails (line 42) | func getGoDetails(f *elf.File) (string, string, error) {
  function dataStart (line 111) | func dataStart(f *elf.File) uint64 {
  function readData (line 125) | func readData(f *elf.File, addr, size uint64) ([]byte, error) {
  function readString (line 144) | func readString(f *elf.File, ptrSize int, readPtr func([]byte) uint64, a...
  function parseModules (line 158) | func parseModules(mod string) map[string]string {
  function decodeString (line 180) | func decodeString(data []byte) (s string, rest []byte) {

FILE: pkg/process/ptrace/cwrapper_linux.go
  function waitpid (line 13) | func waitpid(pid int) int {

FILE: pkg/process/ptrace/ptrace_linux.go
  constant waitPidErrorMessage (line 13) | waitPidErrorMessage = "waitpid ret value: %d"
  constant ptrSize (line 18) | ptrSize = 4 << uintptr(^uintptr(0)>>63)
  type TracedProgram (line 23) | type TracedProgram struct
    method Pid (line 34) | func (p *TracedProgram) Pid() int {
    method Detach (line 149) | func (p *TracedProgram) Detach() error {
    method Protect (line 164) | func (p *TracedProgram) Protect() error {
    method Restore (line 179) | func (p *TracedProgram) Restore() error {
    method Wait (line 194) | func (p *TracedProgram) Wait() error {
    method Step (line 200) | func (p *TracedProgram) Step() error {
    method Mmap (line 210) | func (p *TracedProgram) Mmap(length uint64, fd uint64) (uint64, error) {
  function waitPid (line 38) | func waitPid(pid int) error {
  function Trace (line 48) | func Trace(pid int, logger logr.Logger) (*TracedProgram, error) {

FILE: pkg/process/ptrace/ptrace_linux_amd64.go
  constant syscallInstrSize (line 10) | syscallInstrSize = 2
  function getIp (line 12) | func getIp(regs *syscall.PtraceRegs) uintptr {
  function getRegs (line 16) | func getRegs(pid int, regsout *syscall.PtraceRegs) error {
  function setRegs (line 25) | func setRegs(pid int, regs *syscall.PtraceRegs) error {
  method Syscall (line 35) | func (p *TracedProgram) Syscall(number uint64, args ...uint64) (uint64, ...

FILE: pkg/process/ptrace/ptrace_linux_arm64.go
  constant syscallInstrSize (line 13) | syscallInstrSize = 4
  constant nrPRStatus (line 16) | nrPRStatus = 1
  function getIp (line 18) | func getIp(regs *syscall.PtraceRegs) uintptr {
  function getRegs (line 22) | func getRegs(pid int, regsout *syscall.PtraceRegs) error {
  function setRegs (line 30) | func setRegs(pid int, regs *syscall.PtraceRegs) error {
  method Syscall (line 39) | func (p *TracedProgram) Syscall(number uint64, args ...uint64) (uint64, ...

FILE: pkg/process/ret_linux_amd64.go
  function findRetInstructions (line 8) | func findRetInstructions(data []byte) ([]uint64, error) {

FILE: pkg/process/ret_linux_arm64.go
  constant armInstructionSize (line 9) | armInstructionSize = 4
  function findRetInstructions (line 12) | func findRetInstructions(data []byte) ([]uint64, error) {
Condensed preview — 80 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (650K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 501,
    "preview": "---\nname: Bug Report\nabout: Template for bug reports\nlabels: kind/bug\n---\n\n# Expected Behavior\n\n# Actual Behavior\n\n# Ste"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "chars": 459,
    "preview": "---\nname: Feature Request\nabout: Template for feature requests\nlabels: kind/feature\n---\n\n### Feature request\n\n<!-- Pleas"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 485,
    "preview": "#### What type of this PR\nExamples of user facing changes:\n- API changes\n- Bug fixes\n<!-- \nDescribe your changes here- i"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 726,
    "preview": "name: Release\non:\n  push:\n    tags:\n    - 'v*.*.*'\njobs:\n  docker:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Set"
  },
  {
    "path": ".gitignore",
    "chars": 60,
    "preview": "**/bpf_bpfel.go\n**/bpf_bpfel.o\n/.idea/\nkv-go-instrumentation"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1926,
    "preview": "# Contributing Guide\n\n- [New Contributor Guide](#contributing-guide)\n  - [Ways to Contribute](#ways-to-contribute)\n  - ["
  },
  {
    "path": "Dockerfile",
    "chars": 430,
    "preview": "FROM fedora:35 as builder\nARG TARGETARCH\nRUN dnf install clang llvm make libbpf-devel -y\nRUN curl -LO https://go.dev/dl/"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "Makefile",
    "chars": 585,
    "preview": "# Obtain an absolute path to the directory of the Makefile.\n# Assume the Makefile is in the root of the repository.\nREPO"
  },
  {
    "path": "README.md",
    "chars": 1429,
    "preview": "# OpenTelemetry Auto-Instrumentation for Go\n\nThis project adds [OpenTelemetry instrumentation](https://opentelemetry.io/"
  },
  {
    "path": "cli/main.go",
    "chars": 2295,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pk"
  },
  {
    "path": "docs/design/context-propagation.md",
    "chars": 7031,
    "preview": "# Design Proposal: Context Propagation\n\n## Motivation\n\nContext propagation is a mechanism that allows tracing to be prop"
  },
  {
    "path": "docs/design/manual-instrumentation.md",
    "chars": 2058,
    "preview": "# Design Proposal: Integration with Manual Instrumentation\n\n## Motivation\n\nUsers may want to enrich the traces produced "
  },
  {
    "path": "docs/getting-started/README.md",
    "chars": 5151,
    "preview": "# Getting Started with Go OpenTelemetry Automatic Instrumentation\n\nIn this tutorial, we will walk through how to get sta"
  },
  {
    "path": "docs/getting-started/emojivoto/emoji.yml",
    "chars": 1173,
    "preview": "kind: ServiceAccount\napiVersion: v1\nmetadata:\n  name: emoji\n  namespace: emojivoto\n---\napiVersion: apps/v1\nkind: Deploym"
  },
  {
    "path": "docs/getting-started/emojivoto/kustomization.yml",
    "chars": 70,
    "preview": "resources:\n- ns.yml\n- web.yml\n- emoji.yml\n- voting.yml\n- vote-bot.yml\n"
  },
  {
    "path": "docs/getting-started/emojivoto/ns.yml",
    "chars": 59,
    "preview": "apiVersion: v1\nkind: Namespace\nmetadata:\n  name: emojivoto\n"
  },
  {
    "path": "docs/getting-started/emojivoto/vote-bot.yml",
    "chars": 671,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: vote-bot\n  namespace: emojivoto\n  labels:\n    app.kubernetes.io/n"
  },
  {
    "path": "docs/getting-started/emojivoto/voting.yml",
    "chars": 1183,
    "preview": "kind: ServiceAccount\napiVersion: v1\nmetadata:\n  name: voting\n  namespace: emojivoto\n---\napiVersion: apps/v1\nkind: Deploy"
  },
  {
    "path": "docs/getting-started/emojivoto/web.yml",
    "chars": 1225,
    "preview": "kind: ServiceAccount\napiVersion: v1\nmetadata:\n  name: web\n  namespace: emojivoto\n---\napiVersion: apps/v1\nkind: Deploymen"
  },
  {
    "path": "docs/getting-started/emojivoto-instrumented.yaml",
    "chars": 6721,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: emoji\n  namespace: emojivoto\n  labels:\n    app.kubernetes.io/name"
  },
  {
    "path": "docs/getting-started/jaeger.yaml",
    "chars": 572,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    app: jaeger\n  name: jaeger\nspec:\n  replicas: 1\n  selector:\n"
  },
  {
    "path": "docs/how-it-works.md",
    "chars": 5786,
    "preview": "# OpenTelemtry Go Instrumentation - How it works\n\nWe aim to bring the automatic instrumentation experience found in lang"
  },
  {
    "path": "go.mod",
    "chars": 1387,
    "preview": "module github.com/keyval-dev/opentelemetry-go-instrumentation\n\ngo 1.18\n\nrequire (\n\tgithub.com/cilium/ebpf v0.8.0\n\tgithub"
  },
  {
    "path": "go.sum",
    "chars": 48574,
    "preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
  },
  {
    "path": "include/alloc.h",
    "chars": 2532,
    "preview": "#include \"bpf_helpers.h\"\n\n#define MAX_ENTRIES 50\n\n// Injected in init\nvolatile const u32 total_cpus;\nvolatile const u64 "
  },
  {
    "path": "include/arguments.h",
    "chars": 1164,
    "preview": "#include \"common.h\"\n#include \"bpf_tracing.h\"\n#include \"bpf_helpers.h\"\n#include <stdbool.h>\n\n// Injected in init\nvolatile"
  },
  {
    "path": "include/common.h",
    "chars": 2710,
    "preview": "// This is a compact version of `vmlinux.h`\n\n#define MAX_OS_THREADS 20\n\n#ifndef __VMLINUX_H__\n#define __VMLINUX_H__\n\ntyp"
  },
  {
    "path": "include/go_context.h",
    "chars": 659,
    "preview": "#include \"bpf_helpers.h\"\n\n#define MAX_DISTANCE 10\n\nstatic __always_inline void* find_context_in_map(void *ctx, void *con"
  },
  {
    "path": "include/go_types.h",
    "chars": 2580,
    "preview": "#include \"alloc.h\"\n#include \"bpf_helpers.h\"\n\n#define MAX_REALLOCATION 400\n#define MAX_DATA_SIZE 400\n\nstruct go_string {\n"
  },
  {
    "path": "include/libbpf/bpf.h",
    "chars": 10066,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n\n/*\n * common eBPF ELF operations.\n *\n * Copyright (C) 2013-20"
  },
  {
    "path": "include/libbpf/bpf_core_read.h",
    "chars": 17992,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n#ifndef __BPF_CORE_READ_H__\n#define __BPF_CORE_READ_H__\n\n/*\n *"
  },
  {
    "path": "include/libbpf/bpf_endian.h",
    "chars": 3750,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n#ifndef __BPF_ENDIAN__\n#define __BPF_ENDIAN__\n\n/*\n * Isolate b"
  },
  {
    "path": "include/libbpf/bpf_helper_defs.h",
    "chars": 149473,
    "preview": "/* This is auto-generated file. See bpf_doc.py for details. */\n\n/* Forward declarations of BPF structs */\nstruct bpf_fib"
  },
  {
    "path": "include/libbpf/bpf_helpers.h",
    "chars": 7679,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n#ifndef __BPF_HELPERS__\n#define __BPF_HELPERS__\n\n/*\n * Note th"
  },
  {
    "path": "include/libbpf/bpf_tracing.h",
    "chars": 21512,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n#ifndef __BPF_TRACING_H__\n#define __BPF_TRACING_H__\n\n/* Scan t"
  },
  {
    "path": "include/libbpf/btf.h",
    "chars": 12856,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n/* Copyright (c) 2018 Facebook */\n\n#ifndef __LIBBPF_BTF_H\n#def"
  },
  {
    "path": "include/libbpf/libbpf.h",
    "chars": 33279,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n\n/*\n * Common eBPF ELF object loading operations.\n *\n * Copyri"
  },
  {
    "path": "include/libbpf/libbpf_common.h",
    "chars": 1421,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n\n/*\n * Common user-facing libbpf helpers.\n *\n * Copyright (c) "
  },
  {
    "path": "include/libbpf/libbpf_legacy.h",
    "chars": 1525,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n\n/*\n * Libbpf legacy APIs (either discouraged or deprecated, a"
  },
  {
    "path": "include/libbpf/libbpf_version.h",
    "chars": 242,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n/* Copyright (C) 2021 Facebook */\n#ifndef __LIBBPF_VERSION_H\n#"
  },
  {
    "path": "include/libbpf/skel_internal.h",
    "chars": 2894,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n/* Copyright (c) 2021 Facebook */\n#ifndef __SKEL_INTERNAL_H\n#d"
  },
  {
    "path": "include/libbpf/xsk.h",
    "chars": 8608,
    "preview": "/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */\n\n/*\n * AF_XDP user-space access library.\n *\n * Copyright (c) 2"
  },
  {
    "path": "include/span_context.h",
    "chars": 1604,
    "preview": "#include \"utils.h\"\n\n#define SPAN_CONTEXT_STRING_SIZE 55\n#define MAX_CONCURRENT_SPANS 100\n\nstruct span_context {\n    unsi"
  },
  {
    "path": "include/utils.h",
    "chars": 1588,
    "preview": "#include \"bpf_helpers.h\"\n\n#define TRACE_ID_SIZE 16\n#define TRACE_ID_STRING_SIZE 32\n#define SPAN_ID_SIZE 8\n#define SPAN_I"
  },
  {
    "path": "pkg/errors/errors.go",
    "chars": 344,
    "preview": "package errors\n\nimport \"errors\"\n\n// ErrInterrupted can be used as an error to signal that a process was\n// interrupted b"
  },
  {
    "path": "pkg/inject/data.go",
    "chars": 485,
    "preview": "package inject\n\ntype TrackedOffsets struct {\n\tData []TrackedLibrary `json:\"data\"`\n}\n\ntype TrackedLibrary struct {\n\tName "
  },
  {
    "path": "pkg/inject/injector.go",
    "chars": 2491,
    "preview": "package inject\n\nimport (\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"github.com/cilium/ebpf\"\n\t\"github.com/keyval-dev/opentelemetry-go-"
  },
  {
    "path": "pkg/inject/offset_results.json",
    "chars": 136371,
    "preview": "{\n  \"data\": [\n    {\n      \"name\": \"go\",\n      \"data_members\": [\n        {\n          \"struct\": \"net/http.Request\",\n      "
  },
  {
    "path": "pkg/instrumentors/allocator/allocator_linux.go",
    "chars": 1009,
    "preview": "package allocator\n\nimport (\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/instrumentors/bpffs\"\n\t\"github.c"
  },
  {
    "path": "pkg/instrumentors/api.go",
    "chars": 371,
    "preview": "package instrumentors\n\nimport (\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/instrumentors/context\"\n\t\"gi"
  },
  {
    "path": "pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c",
    "chars": 3189,
    "preview": "#include \"arguments.h\"\n#include \"span_context.h\"\n#include \"go_context.h\"\n\nchar __license[] SEC(\"license\") = \"Dual MIT/GP"
  },
  {
    "path": "pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go",
    "chars": 4646,
    "preview": "package mux\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg"
  },
  {
    "path": "pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c",
    "chars": 6027,
    "preview": "#include \"arguments.h\"\n#include \"go_types.h\"\n#include \"span_context.h\"\n#include \"go_context.h\"\n\nchar __license[] SEC(\"li"
  },
  {
    "path": "pkg/instrumentors/bpf/google/golang/org/grpc/probe.go",
    "chars": 6024,
    "preview": "package grpc\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"github.com/cilium/ebpf\"\n\t\"github.com/keyval-dev/opentelem"
  },
  {
    "path": "pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c",
    "chars": 5520,
    "preview": "#include \"arguments.h\"\n#include \"go_types.h\"\n#include \"span_context.h\"\n\nchar __license[] SEC(\"license\") = \"Dual MIT/GPL\""
  },
  {
    "path": "pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go",
    "chars": 5864,
    "preview": "package server\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/"
  },
  {
    "path": "pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c",
    "chars": 3194,
    "preview": "#include \"arguments.h\"\n#include \"span_context.h\"\n#include \"go_context.h\"\n\nchar __license[] SEC(\"license\") = \"Dual MIT/GP"
  },
  {
    "path": "pkg/instrumentors/bpf/net/http/server/probe.go",
    "chars": 4615,
    "preview": "package server\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/"
  },
  {
    "path": "pkg/instrumentors/bpffs/bpfsfs.go",
    "chars": 52,
    "preview": "package bpffs\n\nconst (\n\tBpfFsPath = \"/sys/fs/bpf\"\n)\n"
  },
  {
    "path": "pkg/instrumentors/context/inst_context.go",
    "chars": 337,
    "preview": "package context\n\nimport (\n\t\"github.com/cilium/ebpf/link\"\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/in"
  },
  {
    "path": "pkg/instrumentors/context/span_context.go",
    "chars": 135,
    "preview": "package context\n\nimport \"go.opentelemetry.io/otel/trace\"\n\ntype EbpfSpanContext struct {\n\tTraceID trace.TraceID\n\tSpanID  "
  },
  {
    "path": "pkg/instrumentors/events/event.go",
    "chars": 374,
    "preview": "package events\n\nimport (\n\t\"go.opentelemetry.io/otel/attribute\"\n\t\"go.opentelemetry.io/otel/trace\"\n)\n\ntype Event struct {\n"
  },
  {
    "path": "pkg/instrumentors/manager.go",
    "chars": 3156,
    "preview": "package instrumentors\n\nimport (\n\t\"fmt\"\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/instrumentors/alloca"
  },
  {
    "path": "pkg/instrumentors/runner.go",
    "chars": 2139,
    "preview": "package instrumentors\n\nimport (\n\t\"fmt\"\n\t\"github.com/cilium/ebpf/link\"\n\t\"github.com/cilium/ebpf/rlimit\"\n\t\"github.com/keyv"
  },
  {
    "path": "pkg/log/logger.go",
    "chars": 259,
    "preview": "package log\n\nimport (\n\t\"github.com/go-logr/logr\"\n\t\"github.com/go-logr/zapr\"\n\t\"go.uber.org/zap\"\n)\n\nvar Logger logr.Logger"
  },
  {
    "path": "pkg/opentelemetry/controller.go",
    "chars": 6075,
    "preview": "package opentelemetry\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"runtime\"\n\t\"time\"\n\n\t\"github.com/keyval-dev/opentelemetry-go-ins"
  },
  {
    "path": "pkg/opentelemetry/id_generator.go",
    "chars": 1169,
    "preview": "package opentelemetry\n\nimport (\n\t\"context\"\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/instrumentors/ev"
  },
  {
    "path": "pkg/process/analyze.go",
    "chars": 3320,
    "preview": "package process\n\nimport (\n\t\"debug/elf\"\n\t\"errors\"\n\t\"fmt\"\n\t\"github.com/hashicorp/go-version\"\n\t\"github.com/keyval-dev/opent"
  },
  {
    "path": "pkg/process/args.go",
    "chars": 730,
    "preview": "package process\n\nimport (\n\t\"errors\"\n\t\"flag\"\n\t\"os\"\n)\n\nconst (\n\tExePathEnvVar = \"OTEL_TARGET_EXE\"\n)\n\ntype TargetArgs struc"
  },
  {
    "path": "pkg/process/discover.go",
    "chars": 2231,
    "preview": "package process\n\nimport (\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/errors\"\n\t\"github.com/keyval-dev/o"
  },
  {
    "path": "pkg/process/funcs_nonstripped.go",
    "chars": 2634,
    "preview": "package process\n\nimport (\n\t\"debug/elf\"\n\t\"errors\"\n\t\"fmt\"\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pkg/log"
  },
  {
    "path": "pkg/process/funcs_stripped.go",
    "chars": 2297,
    "preview": "package process\n\nimport (\n\t\"debug/elf\"\n\t\"debug/gosym\"\n\t\"fmt\"\n\t\"github.com/keyval-dev/opentelemetry-go-instrumentation/pk"
  },
  {
    "path": "pkg/process/module.go",
    "chars": 4778,
    "preview": "package process\n\nimport (\n\t\"bytes\"\n\t\"debug/elf\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"github.com/hashicorp/go-version\"\n\t"
  },
  {
    "path": "pkg/process/ptrace/cwrapper_linux.go",
    "chars": 212,
    "preview": "//go:build cgo\n\npackage ptrace\n\n/*\n#define _GNU_SOURCE\n#include <sys/wait.h>\n#include <sys/uio.h>\n#include <errno.h>\n*/\n"
  },
  {
    "path": "pkg/process/ptrace/ptrace_linux.go",
    "chars": 4668,
    "preview": "package ptrace\n\nimport (\n\t\"fmt\"\n\t\"github.com/go-logr/logr\"\n\t\"github.com/pkg/errors\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\t\"syscal"
  },
  {
    "path": "pkg/process/ptrace/ptrace_linux_amd64.go",
    "chars": 2388,
    "preview": "package ptrace\n\nimport (\n\t\"encoding/binary\"\n\t\"syscall\"\n\n\t\"github.com/pkg/errors\"\n)\n\nconst syscallInstrSize = 2\n\nfunc get"
  },
  {
    "path": "pkg/process/ptrace/ptrace_linux_arm64.go",
    "chars": 2280,
    "preview": "package ptrace\n\nimport (\n\t\"encoding/binary\"\n\t\"syscall\"\n\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x/sys/unix\"\n)\n\nvar endian "
  },
  {
    "path": "pkg/process/ret_linux_amd64.go",
    "chars": 516,
    "preview": "package process\n\nimport (\n\t\"fmt\"\n\t\"golang.org/x/arch/x86/x86asm\"\n)\n\nfunc findRetInstructions(data []byte) ([]uint64, err"
  },
  {
    "path": "pkg/process/ret_linux_arm64.go",
    "chars": 502,
    "preview": "package process\n\nimport (\n\t\"golang.org/x/arch/arm64/arm64asm\"\n)\n\nconst (\n\t// In ARM64 each instruction is 4 bytes in len"
  }
]

About this extraction

This page contains the full source code of the keyval-dev/opentelemetry-go-instrumentation GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 80 files (592.2 KB), approximately 182.7k tokens, and a symbol index with 875 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!