diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index 08305eefc9..8b37a2e16c 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -23,7 +23,7 @@ jobs: with: persist-credentials: false - - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + - uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 with: results_file: results.sarif results_format: sarif diff --git a/.gitignore b/.gitignore index ff6f525f44..8f2b1251a3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ .tools/ **/internal/test/e2e/*/main +# ctags file +tags + # Python pip cache. .cache/ diff --git a/Makefile b/Makefile index 80f14cd6a1..a1e5effb88 100644 --- a/Makefile +++ b/Makefile @@ -89,8 +89,11 @@ $(BEAR): $(TOOLS) rm -rf /tmp/Bear; \ fi +# Compiled in the Pixie repo via `bazel build //src/stirling/binaries:go_func_dwarf_dump` +DWARF_READER_DUMPER = internal/tools/inspect/go_func_dwarf_dump + .PHONY: tools -tools: $(GOLICENSES) $(MULTIMOD) $(GOLANGCI_LINT) $(DBOTCONF) $(OFFSETGEN) $(SYNCLIBBPF) $(CROSSLINK) $(BEAR) +tools: $(GOLICENSES) $(MULTIMOD) $(GOLANGCI_LINT) $(DBOTCONF) $(OFFSETGEN) $(SYNCLIBBPF) $(CROSSLINK) $(BEAR) $(DWARF_READER_DUMPER) TEST_TARGETS := test-verbose test-ebpf test-race .PHONY: $(TEST_TARGETS) test diff --git a/examples/kafka-go/consumer/go.mod b/examples/kafka-go/consumer/go.mod index 9d9b71f1c6..b6c636a5e3 100644 --- a/examples/kafka-go/consumer/go.mod +++ b/examples/kafka-go/consumer/go.mod @@ -9,7 +9,7 @@ require ( ) require ( - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/klauspost/compress v1.18.0 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect diff --git a/examples/kafka-go/consumer/go.sum b/examples/kafka-go/consumer/go.sum index fdf5fcba43..c22e5f64f9 100644 --- a/examples/kafka-go/consumer/go.sum +++ b/examples/kafka-go/consumer/go.sum @@ -2,8 +2,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= diff --git a/examples/rolldice/user/go.mod b/examples/rolldice/user/go.mod index 01e9be0375..8b8fde7340 100644 --- a/examples/rolldice/user/go.mod +++ b/examples/rolldice/user/go.mod @@ -8,7 +8,7 @@ require ( ) require ( - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/otel/metric v1.36.0 // indirect diff --git a/examples/rolldice/user/go.sum b/examples/rolldice/user/go.sum index 4c978445ea..78a72301d7 100644 --- a/examples/rolldice/user/go.sum +++ b/examples/rolldice/user/go.sum @@ -1,8 +1,8 @@ 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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= diff --git a/go.mod b/go.mod index 91a38655dd..1217e4592b 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect @@ -70,12 +70,12 @@ require ( go.opentelemetry.io/otel/metric v1.36.0 // indirect go.opentelemetry.io/otel/sdk/log v0.12.2 // indirect go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect - go.opentelemetry.io/proto/otlp v1.6.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.40.0 // indirect golang.org/x/text v0.25.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/protobuf v1.36.6 // indirect ) diff --git a/go.sum b/go.sum index 11922b1693..287db890c6 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6 h1:teYtXy9B7y5lHTp8V9KPxpYRAVA7dozigQcMiBust1s= @@ -122,8 +122,8 @@ go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFw go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= -go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= -go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= +go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= +go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -163,10 +163,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= -google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= diff --git a/internal/pkg/funcfield/funcfield.go b/internal/pkg/funcfield/funcfield.go new file mode 100644 index 0000000000..fc92c06cfc --- /dev/null +++ b/internal/pkg/funcfield/funcfield.go @@ -0,0 +1,193 @@ +package funcfield + +import ( + "errors" + "fmt" + "sort" + "strings" + "sync" + + "github.com/Masterminds/semver/v3" +) + +// // ID identifies a function argument or return value. +type ID struct { + // ModPath is the module path containing the struct field package. + // + // If set to "std", the struct field belongs to the standard Go library. + ModPath string + // PkgPath package import path containing the struct field. + PkgPath string + // Struct is the name of the struct containing the field. + Func string + // Field is the field name. + Arg string +} + +// NewID returns a new ID using pkg for the PkgPath, strct for the Struct, and +// field for the Field. +func NewID(mod, pkg, fn, arg string) ID { + return ID{ModPath: mod, PkgPath: pkg, Func: fn, Arg: arg} +} + +type UniqueOffset struct { + Value uint64 + Location Location + Valid bool +} + +// Offsets holds byte offsets for function arguments and return values. +type Offsets struct { + Mu sync.RWMutex + Values map[VerKey]OffsetVersion + Ua UniqueOffset +} + +func (o *Offsets) GetLatest() (OffsetKey, VerKey) { + o.Mu.RLock() + defer o.Mu.RUnlock() + + latestVersion := VerKey{} + val := OffsetKey{} + for verKey, ov := range o.Values { + // TODO(ddelnano): This needs to handle differences in the Location as well. + // for now this doesn't matter since for the ABIInternal (more recent Go ABI) + // would have to pass many arguments to spill over to the stack. + if verKey.GreaterThan(latestVersion) && ov.Offset.Valid { + latestVersion = verKey + val = ov.Offset + } + } + + return val, latestVersion +} + +func (o *Offsets) Index() map[OffsetKey][]*semver.Version { + o.Mu.RLock() + defer o.Mu.RUnlock() + + out := make(map[OffsetKey][]*semver.Version) + for _, ov := range o.Values { + vers, ok := out[ov.Offset] + if ok { + i := sort.Search(len(vers), func(i int) bool { + return vers[i].GreaterThanEqual(ov.Version) + }) + vers = append(vers, nil) + copy(vers[i+1:], vers[i:]) + vers[i] = ov.Version + } else { + vers = append(vers, ov.Version) + } + out[ov.Offset] = vers + } + return out +} + +func (v VerKey) GreaterThan(other VerKey) bool { + return v.Version.GreaterThan(&other.Version) +} + +// NewOffsets initializes an empty Offsets structure. +func NewOffsets() *Offsets { + return &Offsets{Values: make(map[VerKey]OffsetVersion)} +} + +// Get retrieves an offset and location for a given version. +func (o *Offsets) Get(ver *semver.Version) (OffsetKey, bool) { + if o == nil { + return OffsetKey{}, false + } + o.Mu.RLock() + v, ok := o.Values[NewVerKey(ver)] + o.Mu.RUnlock() + + // TODO(ddelnano): The Location should be checked here. For now this doesn't + // matter since for the ABIInternal (more recent Go ABI) would have to pass + // many arguments to spill over to the stack. + if strings.HasPrefix(ver.String(), "0.0.0") && !ok && o.Ua.Valid { + return OffsetKey{Offset: o.Ua.Value, Valid: true, Location: o.Ua.Location}, true + } + + return v.Offset, ok +} + +// // Put stores an offset and location type for a given version. +func (o *Offsets) Put(ver *semver.Version, offset OffsetKey) { + ov := OffsetVersion{Offset: offset, Version: ver} + o.Mu.Lock() + defer o.Mu.Unlock() + + if o.Values == nil { + o.Values = map[VerKey]OffsetVersion{NewVerKey(ver): ov} + o.Ua.Valid = ov.Offset.Valid + o.Ua.Value = ov.Offset.Offset + o.Ua.Location = ov.Offset.Location + return + } + + o.Values[NewVerKey(ver)] = ov + if o.Ua.Valid && (o.Ua.Value != ov.Offset.Offset || o.Ua.Location != ov.Offset.Location) { + o.Ua.Valid = false + } +} + +// // Struct for version comparison. +type VerKey struct { + semver.Version +} + +func NewVerKey(v *semver.Version) VerKey { + stripped := semver.New(v.Major(), v.Minor(), v.Patch(), v.Prerelease(), v.Metadata()) + return VerKey{Version: *stripped} +} + +type Location int + +const ( + Unknown Location = iota + Stack Location = iota + Registers Location = iota +) + +func (l *Location) UnmarshalJSON(data []byte) error { + switch string(data) { + case `"kStack"`: + fallthrough + case `"stack"`: + *l = Stack + case `"kRegister"`: + fallthrough + case `"registers"`: + *l = Registers + case `"kUnknown"`: + fallthrough + case `"unknown"`: + *l = Unknown + default: + return errors.New(fmt.Sprintf("invalid location %s", string(data))) + } + return nil +} + +func (l *Location) MarshalJSON() ([]byte, error) { + if *l == Unknown { + return []byte(`"unknown"`), nil + } else if *l == Stack { + return []byte(`"stack"`), nil + } else if *l == Registers { + return []byte(`"registers"`), nil + } + return nil, errors.New(fmt.Sprintf("invalid location %d", *l)) +} + +type OffsetKey struct { + Offset uint64 + Location Location + Valid bool +} + +type OffsetVersion struct { + Offset OffsetKey + Version *semver.Version +} diff --git a/internal/pkg/inject/consts.go b/internal/pkg/inject/consts.go index 2648552ffa..42c338bf9c 100644 --- a/internal/pkg/inject/consts.go +++ b/internal/pkg/inject/consts.go @@ -162,7 +162,7 @@ func FindOffset(id structfield.ID, info *process.Info) (structfield.OffsetKey, e return structfield.OffsetKey{}, err } - v, err := process.DWARF{Reader: data.Reader()}.GoStructField(id) + v, err := process.NewDWARF(data).GoStructField(id) if err != nil { return structfield.OffsetKey{}, err } diff --git a/internal/pkg/inject/offset_results.json b/internal/pkg/inject/offset_results.json index b837477513..52b985930c 100644 --- a/internal/pkg/inject/offset_results.json +++ b/internal/pkg/inject/offset_results.json @@ -1,95 +1,60 @@ [ { - "module": "github.com/segmentio/kafka-go", + "module": "golang.org/x/net", "packages": [ { - "package": "github.com/segmentio/kafka-go", + "package": "golang.org/x/net/http2", "structs": [ { - "struct": "Conn", + "struct": "DataFrame", "fields": [ { - "field": "clientID", + "field": "data", "offsets": [ { - "offset": 328, + "offset": 16, "versions": [ "0.1.0", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", - "0.2.4", - "0.2.5", - "0.3.0" - ] - }, - { - "offset": 360, - "versions": [ - "0.3.1", - "0.3.2", - "0.3.3" - ] - }, - { - "offset": 368, - "versions": [ - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", + "0.3.0", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10", - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38", - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] @@ -97,490 +62,213 @@ ] }, { - "struct": "Message", + "struct": "FrameHeader", "fields": [ { - "field": "Headers", - "offsets": [ - { - "offset": null, - "versions": [ - "0.1.0", - "0.2.0", - "0.2.1", - "0.2.2" - ] - }, - { - "offset": 80, - "versions": [ - "0.2.3", - "0.2.4", - "0.2.5", - "0.3.0", - "0.3.1", - "0.3.2", - "0.3.3", - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", - "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10" - ] - }, - { - "offset": 88, - "versions": [ - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38", - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" - ] - } - ] - }, - { - "field": "Key", - "offsets": [ - { - "offset": 32, - "versions": [ - "0.1.0", - "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", - "0.2.4", - "0.2.5", - "0.3.0", - "0.3.1", - "0.3.2", - "0.3.3", - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", - "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10" - ] - }, - { - "offset": 40, - "versions": [ - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38", - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" - ] - } - ] - }, - { - "field": "Offset", + "field": "Flags", "offsets": [ { - "offset": 24, + "offset": 2, "versions": [ "0.1.0", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", - "0.2.4", - "0.2.5", "0.3.0", - "0.3.1", - "0.3.2", - "0.3.3", - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10", - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38", - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] }, { - "field": "Partition", + "field": "StreamID", "offsets": [ { - "offset": 16, + "offset": 8, "versions": [ "0.1.0", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", - "0.2.4", - "0.2.5", "0.3.0", - "0.3.1", - "0.3.2", - "0.3.3", - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10", - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38", - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] }, { - "field": "Time", + "field": "Type", "offsets": [ { - "offset": 80, + "offset": 1, "versions": [ "0.1.0", "0.2.0", - "0.2.1", - "0.2.2" - ] - }, - { - "offset": 104, - "versions": [ - "0.2.3", - "0.2.4", - "0.2.5", "0.3.0", - "0.3.1", - "0.3.2", - "0.3.3", - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10" - ] - }, - { - "offset": 112, - "versions": [ - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38" - ] - }, - { - "offset": 128, - "versions": [ - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] - }, + } + ] + }, + { + "struct": "Framer", + "fields": [ { - "field": "Topic", + "field": "w", "offsets": [ { - "offset": 0, + "offset": 120, "versions": [ "0.1.0", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", - "0.2.4", - "0.2.5", "0.3.0", - "0.3.1", - "0.3.2", - "0.3.3", - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10", - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38", - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] @@ -588,161 +276,55 @@ ] }, { - "struct": "Reader", + "struct": "HeadersFrame", "fields": [ { - "field": "config", + "field": "FrameHeader", "offsets": [ { "offset": 0, "versions": [ "0.1.0", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", - "0.2.4", - "0.2.5", "0.3.0", - "0.3.1", - "0.3.2", - "0.3.3", - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10", - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38", - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" - ] - } - ] - } - ] - }, - { - "struct": "ReaderConfig", - "fields": [ - { - "field": "GroupID", - "offsets": [ - { - "offset": 24, - "versions": [ - "0.1.0", - "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", - "0.2.4", - "0.2.5", - "0.3.0", - "0.3.1", - "0.3.2", - "0.3.3", - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", - "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10", - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38", - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] @@ -750,122 +332,18 @@ ] }, { - "struct": "Writer", - "fields": [ - { - "field": "Topic", - "offsets": [ - { - "offset": null, - "versions": [ - "0.1.0", - "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", - "0.2.4", - "0.2.5", - "0.3.0", - "0.3.1", - "0.3.2", - "0.3.3", - "0.3.4", - "0.3.5", - "0.3.6", - "0.3.7", - "0.3.8", - "0.3.9", - "0.3.10", - "0.4.0" - ] - }, - { - "offset": 16, - "versions": [ - "0.4.1", - "0.4.2", - "0.4.3", - "0.4.4", - "0.4.5", - "0.4.6", - "0.4.7", - "0.4.8", - "0.4.9", - "0.4.10", - "0.4.11", - "0.4.12", - "0.4.13", - "0.4.14", - "0.4.15", - "0.4.16", - "0.4.17", - "0.4.18", - "0.4.19", - "0.4.20", - "0.4.21", - "0.4.22", - "0.4.23", - "0.4.24", - "0.4.25", - "0.4.26", - "0.4.27", - "0.4.28", - "0.4.29", - "0.4.30", - "0.4.31", - "0.4.32-msk-iam", - "0.4.32", - "0.4.33", - "0.4.34", - "0.4.35", - "0.4.38", - "0.4.39", - "0.4.40", - "0.4.41", - "0.4.42", - "0.4.43", - "0.4.44", - "0.4.45", - "0.4.46", - "0.4.47", - "0.4.48" - ] - } - ] - } - ] - } - ] - } - ] - }, - { - "module": "go.opentelemetry.io/otel", - "packages": [ - { - "package": "go.opentelemetry.io/otel/internal/global", - "structs": [ - { - "struct": "tracer", + "struct": "MetaHeadersFrame", "fields": [ { - "field": "delegate", + "field": "Fields", "offsets": [ { - "offset": null, + "offset": 8, "versions": [ "0.1.0", - "0.1.1", - "0.1.2", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", "0.3.0", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", "0.5.0", "0.6.0", "0.7.0", @@ -874,110 +352,49 @@ "0.10.0", "0.11.0", "0.12.0", - "0.13.0" - ] - }, - { - "offset": 40, - "versions": [ - "0.19.0", - "0.20.0" - ] - }, - { - "offset": 48, - "versions": [ - "1.0.0-RC1", - "1.0.0-RC2", - "1.0.0-RC3", - "1.0.0", - "1.0.1", - "1.1.0", - "1.2.0", - "1.3.0", - "1.4.0", - "1.4.1", - "1.5.0", - "1.6.0", - "1.6.1", - "1.6.2", - "1.6.3", - "1.7.0", - "1.8.0", - "1.9.0", - "1.10.0", - "1.11.0", - "1.11.1", - "1.11.2", - "1.12.0", - "1.13.0", - "1.14.0", - "1.15.0-rc.1", - "1.15.0-rc.2", - "1.15.0", - "1.15.1", - "1.16.0-rc.1", - "1.16.0", - "1.17.0", - "1.18.0", - "1.19.0-rc.1", - "1.19.0" - ] - }, - { - "offset": 56, - "versions": [ + "0.13.0", "0.14.0", "0.15.0", "0.16.0", "0.17.0", - "0.18.0" - ] - }, - { - "offset": 64, - "versions": [ - "1.20.0", - "1.21.0", - "1.22.0", - "1.23.0-rc.1", - "1.23.0", - "1.23.1", - "1.24.0", - "1.25.0", - "1.26.0", - "1.27.0", - "1.28.0", - "1.29.0", - "1.30.0", - "1.31.0", - "1.32.0", - "1.33.0", - "1.34.0", - "1.35.0", - "1.36.0" + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] }, { - "field": "name", + "field": "HeadersFrame", "offsets": [ { - "offset": null, + "offset": 0, "versions": [ "0.1.0", - "0.1.1", - "0.1.2", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", "0.3.0", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", "0.5.0", "0.6.0", "0.7.0", @@ -986,100 +403,57 @@ "0.10.0", "0.11.0", "0.12.0", - "0.13.0" - ] - }, - { - "offset": 0, - "versions": [ - "0.19.0", - "0.20.0", - "1.0.0-RC1", - "1.0.0-RC2", - "1.0.0-RC3", - "1.0.0", - "1.0.1", - "1.1.0", - "1.2.0", - "1.3.0", - "1.4.0", - "1.4.1", - "1.5.0", - "1.6.0", - "1.6.1", - "1.6.2", - "1.6.3", - "1.7.0", - "1.8.0", - "1.9.0", - "1.10.0", - "1.11.0", - "1.11.1", - "1.11.2", - "1.12.0", - "1.13.0", - "1.14.0", - "1.15.0-rc.1", - "1.15.0-rc.2", - "1.15.0", - "1.15.1", - "1.16.0-rc.1", - "1.16.0", - "1.17.0", - "1.18.0", - "1.19.0-rc.1", - "1.19.0" - ] - }, - { - "offset": 16, - "versions": [ + "0.13.0", "0.14.0", "0.15.0", "0.16.0", "0.17.0", "0.18.0", - "1.20.0", - "1.21.0", - "1.22.0", - "1.23.0-rc.1", - "1.23.0", - "1.23.1", - "1.24.0", - "1.25.0", - "1.26.0", - "1.27.0", - "1.28.0", - "1.29.0", - "1.30.0", - "1.31.0", - "1.32.0", - "1.33.0", - "1.34.0", - "1.35.0", - "1.36.0" + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] - }, + } + ] + } + ], + "funcs": [ + { + "func": "(*Framer).WriteDataPadded", + "args": [ { - "field": "provider", + "arg": "data", "offsets": [ { - "offset": null, + "offset": 24, + "location": "registers", "versions": [ "0.1.0", - "0.1.1", - "0.1.2", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", "0.3.0", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", "0.5.0", "0.6.0", "0.7.0", @@ -1095,98 +469,43 @@ "0.17.0", "0.18.0", "0.19.0", - "0.20.0" - ] - }, - { - "offset": 40, - "versions": [ - "1.0.0-RC1", - "1.0.0-RC2", - "1.0.0-RC3", - "1.0.0", - "1.0.1", - "1.1.0", - "1.2.0", - "1.3.0", - "1.4.0", - "1.4.1", - "1.5.0", - "1.6.0", - "1.6.1", - "1.6.2", - "1.6.3", - "1.7.0", - "1.8.0", - "1.9.0", - "1.10.0", - "1.11.0", - "1.11.1", - "1.11.2", - "1.12.0", - "1.13.0", - "1.14.0", - "1.15.0-rc.1", - "1.15.0-rc.2", - "1.15.0", - "1.15.1", - "1.16.0-rc.1", - "1.16.0", - "1.17.0", - "1.18.0", - "1.19.0-rc.1", - "1.19.0" - ] - }, - { - "offset": 56, - "versions": [ - "1.20.0", - "1.21.0", - "1.22.0", - "1.23.0-rc.1", - "1.23.0", - "1.23.1", - "1.24.0", - "1.25.0", - "1.26.0", - "1.27.0", - "1.28.0", - "1.29.0", - "1.30.0", - "1.31.0", - "1.32.0", - "1.33.0", - "1.34.0", - "1.35.0", - "1.36.0" + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] - } - ] - }, - { - "struct": "tracerProvider", - "fields": [ + }, { - "field": "tracers", + "arg": "endStream", "offsets": [ { - "offset": null, + "offset": 16, + "location": "registers", "versions": [ "0.1.0", - "0.1.1", - "0.1.2", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", "0.3.0", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", "0.5.0", "0.6.0", "0.7.0", @@ -1195,12 +514,7 @@ "0.10.0", "0.11.0", "0.12.0", - "0.13.0" - ] - }, - { - "offset": 8, - "versions": [ + "0.13.0", "0.14.0", "0.15.0", "0.16.0", @@ -1208,97 +522,42 @@ "0.18.0", "0.19.0", "0.20.0", - "1.0.0-RC1", - "1.0.0-RC2", - "1.0.0-RC3", - "1.0.0", - "1.0.1", - "1.1.0", - "1.2.0", - "1.3.0", - "1.4.0", - "1.4.1", - "1.5.0", - "1.6.0", - "1.6.1", - "1.6.2", - "1.6.3", - "1.7.0", - "1.8.0", - "1.9.0", - "1.10.0", - "1.11.0", - "1.11.1", - "1.11.2", - "1.12.0", - "1.13.0", - "1.14.0", - "1.15.0-rc.1", - "1.15.0-rc.2", - "1.15.0", - "1.15.1", - "1.16.0-rc.1", - "1.16.0", - "1.17.0", - "1.18.0", - "1.19.0-rc.1", - "1.19.0" - ] - }, - { - "offset": 24, - "versions": [ - "1.20.0", - "1.21.0", - "1.22.0", - "1.23.0-rc.1", - "1.23.0", - "1.23.1", - "1.24.0", - "1.25.0", - "1.26.0", - "1.27.0", - "1.28.0", - "1.29.0", - "1.30.0", - "1.31.0", - "1.32.0", - "1.33.0", - "1.34.0", - "1.35.0", - "1.36.0" + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] - } - ] - } - ] - }, - { - "package": "go.opentelemetry.io/otel/trace", - "structs": [ - { - "struct": "SpanContext", - "fields": [ + }, { - "field": "spanID", + "arg": "f", "offsets": [ { - "offset": null, + "offset": 0, + "location": "registers", "versions": [ "0.1.0", - "0.1.1", - "0.1.2", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", "0.3.0", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", "0.5.0", "0.6.0", "0.7.0", @@ -1314,88 +573,43 @@ "0.17.0", "0.18.0", "0.19.0", - "0.20.0" - ] - }, - { - "offset": 16, - "versions": [ - "1.0.0-RC1", - "1.0.0-RC2", - "1.0.0-RC3", - "1.0.0", - "1.0.1", - "1.1.0", - "1.2.0", - "1.3.0", - "1.4.0", - "1.4.1", - "1.5.0", - "1.6.0", - "1.6.1", - "1.6.2", - "1.6.3", - "1.7.0", - "1.8.0", - "1.9.0", - "1.10.0", - "1.11.0", - "1.11.1", - "1.11.2", - "1.12.0", - "1.13.0", - "1.14.0", - "1.15.0-rc.1", - "1.15.0-rc.2", - "1.15.0", - "1.15.1", - "1.16.0-rc.1", - "1.16.0", - "1.17.0", - "1.18.0", - "1.19.0-rc.1", - "1.19.0", - "1.20.0", - "1.21.0", - "1.22.0", - "1.23.0-rc.1", - "1.23.0", - "1.23.1", - "1.24.0", - "1.25.0", - "1.26.0", - "1.27.0", - "1.28.0", - "1.29.0", - "1.30.0", - "1.31.0", - "1.32.0", - "1.33.0", - "1.34.0", - "1.35.0", - "1.36.0" + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] }, { - "field": "traceFlags", + "arg": "streamID", "offsets": [ { - "offset": null, + "offset": 8, + "location": "registers", "versions": [ "0.1.0", - "0.1.1", - "0.1.2", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", "0.3.0", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", "0.5.0", "0.6.0", "0.7.0", @@ -1411,88 +625,100 @@ "0.17.0", "0.18.0", "0.19.0", - "0.20.0" + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] - }, + } + ] + } + ] + }, + { + "func": "(*Framer).checkFrameOrder", + "args": [ + { + "arg": "f", + "offsets": [ { - "offset": 24, + "offset": 8, + "location": "registers", "versions": [ - "1.0.0-RC1", - "1.0.0-RC2", - "1.0.0-RC3", - "1.0.0", - "1.0.1", - "1.1.0", - "1.2.0", - "1.3.0", - "1.4.0", - "1.4.1", - "1.5.0", - "1.6.0", - "1.6.1", - "1.6.2", - "1.6.3", - "1.7.0", - "1.8.0", - "1.9.0", - "1.10.0", - "1.11.0", - "1.11.1", - "1.11.2", - "1.12.0", - "1.13.0", - "1.14.0", - "1.15.0-rc.1", - "1.15.0-rc.2", - "1.15.0", - "1.15.1", - "1.16.0-rc.1", - "1.16.0", - "1.17.0", - "1.18.0", - "1.19.0-rc.1", - "1.19.0", - "1.20.0", - "1.21.0", - "1.22.0", - "1.23.0-rc.1", - "1.23.0", - "1.23.1", - "1.24.0", - "1.25.0", - "1.26.0", - "1.27.0", - "1.28.0", - "1.29.0", - "1.30.0", - "1.31.0", - "1.32.0", - "1.33.0", - "1.34.0", - "1.35.0", - "1.36.0" + "0.1.0", + "0.2.0", + "0.3.0", + "0.4.0", + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] }, { - "field": "traceID", + "arg": "fr", "offsets": [ { - "offset": null, + "offset": 0, + "location": "registers", "versions": [ "0.1.0", - "0.1.1", - "0.1.2", "0.2.0", - "0.2.1", - "0.2.2", - "0.2.3", "0.3.0", "0.4.0", - "0.4.1", - "0.4.2", - "0.4.3", "0.5.0", "0.6.0", "0.7.0", @@ -1508,66 +734,28 @@ "0.17.0", "0.18.0", "0.19.0", - "0.20.0" - ] - }, - { - "offset": 0, - "versions": [ - "1.0.0-RC1", - "1.0.0-RC2", - "1.0.0-RC3", - "1.0.0", - "1.0.1", - "1.1.0", - "1.2.0", - "1.3.0", - "1.4.0", - "1.4.1", - "1.5.0", - "1.6.0", - "1.6.1", - "1.6.2", - "1.6.3", - "1.7.0", - "1.8.0", - "1.9.0", - "1.10.0", - "1.11.0", - "1.11.1", - "1.11.2", - "1.12.0", - "1.13.0", - "1.14.0", - "1.15.0-rc.1", - "1.15.0-rc.2", - "1.15.0", - "1.15.1", - "1.16.0-rc.1", - "1.16.0", - "1.17.0", - "1.18.0", - "1.19.0-rc.1", - "1.19.0", - "1.20.0", - "1.21.0", - "1.22.0", - "1.23.0-rc.1", - "1.23.0", - "1.23.1", - "1.24.0", - "1.25.0", - "1.26.0", - "1.27.0", - "1.28.0", - "1.29.0", - "1.30.0", - "1.31.0", - "1.32.0", - "1.33.0", - "1.34.0", - "1.35.0", - "1.36.0" + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" ] } ] @@ -1575,23 +763,69 @@ ] } ] - } - ] - }, - { - "module": "golang.org/x/net", - "packages": [ + }, { - "package": "golang.org/x/net/http2", + "package": "golang.org/x/net/http2/hpack", "structs": [ { - "struct": "FrameHeader", + "struct": "HeaderField", "fields": [ { - "field": "StreamID", + "field": "Name", "offsets": [ { - "offset": 8, + "offset": 0, + "versions": [ + "0.1.0", + "0.2.0", + "0.3.0", + "0.4.0", + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" + ] + } + ] + }, + { + "field": "Value", + "offsets": [ + { + "offset": 16, "versions": [ "0.1.0", "0.2.0", @@ -1632,21 +866,77 @@ "0.37.0", "0.38.0", "0.39.0", - "0.40.0" + "0.40.0", + "0.41.0" ] } ] } ] - }, + } + ], + "funcs": [ { - "struct": "MetaHeadersFrame", - "fields": [ + "func": "(*Encoder).WriteField", + "args": [ { - "field": "Fields", + "arg": "e", + "offsets": [ + { + "offset": 0, + "location": "registers", + "versions": [ + "0.1.0", + "0.2.0", + "0.3.0", + "0.4.0", + "0.5.0", + "0.6.0", + "0.7.0", + "0.8.0", + "0.9.0", + "0.10.0", + "0.11.0", + "0.12.0", + "0.13.0", + "0.14.0", + "0.15.0", + "0.16.0", + "0.17.0", + "0.18.0", + "0.19.0", + "0.20.0", + "0.21.0", + "0.22.0", + "0.23.0", + "0.24.0", + "0.25.0", + "0.26.0", + "0.27.0", + "0.28.0", + "0.29.0", + "0.30.0", + "0.31.0", + "0.32.0", + "0.33.0", + "0.34.0", + "0.35.0", + "0.36.0", + "0.37.0", + "0.38.0", + "0.39.0", + "0.40.0", + "0.41.0" + ] + } + ] + }, + { + "arg": "f", "offsets": [ { "offset": 8, + "location": "registers", "versions": [ "0.1.0", "0.2.0", @@ -1687,7 +977,8 @@ "0.37.0", "0.38.0", "0.39.0", - "0.40.0" + "0.40.0", + "0.41.0" ] } ] @@ -1699,16 +990,16 @@ ] }, { - "module": "google.golang.org/grpc", + "module": "google.golang.org", "packages": [ { - "package": "google.golang.org/genproto/googleapis/rpc/status", + "package": "google.golang.org/grpc/credentials/internal", "structs": [ { - "struct": "Status", + "struct": "syscallConn", "fields": [ { - "field": "Code", + "field": "conn", "offsets": [ { "offset": null, @@ -1734,19 +1025,30 @@ "1.7.2", "1.7.3", "1.7.4", - "1.7.5" - ] - }, - { - "offset": 0, - "versions": [ - "1.15.0", - "1.16.0", - "1.17.0", - "1.18.0", - "1.18.1", - "1.19.0", - "1.19.1", + "1.7.5", + "1.8.0", + "1.8.2", + "1.9.0", + "1.9.1", + "1.9.2", + "1.10.0", + "1.10.1", + "1.11.0", + "1.11.1", + "1.11.2", + "1.11.3", + "1.12.0", + "1.12.1", + "1.12.2", + "1.13.0", + "1.14.0", + "1.15.0", + "1.16.0", + "1.17.0", + "1.18.0", + "1.18.1", + "1.19.0", + "1.19.1", "1.20.0", "1.20.1", "1.21.0", @@ -1785,30 +1087,9 @@ "1.33.0-dev", "1.33.0", "1.33.1", - "1.34.0-dev" - ] - }, - { - "offset": 40, - "versions": [ - "1.8.0", - "1.8.2", - "1.9.0", - "1.9.1", - "1.9.2", - "1.10.0", - "1.10.1", - "1.11.0", - "1.11.1", - "1.11.2", - "1.11.3", - "1.12.0", - "1.12.1", - "1.12.2", - "1.13.0", - "1.14.0", "1.33.2", "1.33.3", + "1.34.0-dev", "1.34.0", "1.34.1", "1.34.2", @@ -1932,13 +1213,31 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] - }, + } + ] + } + ], + "funcs": null + } + ] + }, + { + "module": "google.golang.org/grpc", + "packages": [ + { + "package": "google.golang.org/grpc/internal/transport", + "structs": [ + { + "struct": "bufWriter", + "fields": [ { - "field": "Message", + "field": "conn", "offsets": [ { "offset": null, @@ -1965,12 +1264,27 @@ "1.7.3", "1.7.4", "1.7.5", - "1.64.0" + "1.8.0", + "1.8.2", + "1.9.0", + "1.9.1", + "1.9.2", + "1.10.0", + "1.10.1", + "1.11.0", + "1.11.1", + "1.11.2", + "1.11.3", + "1.12.0", + "1.12.1", + "1.12.2", + "1.13.0" ] }, { - "offset": 8, + "offset": 40, "versions": [ + "1.14.0", "1.15.0", "1.16.0", "1.17.0", @@ -2016,30 +1330,9 @@ "1.33.0-dev", "1.33.0", "1.33.1", - "1.34.0-dev" - ] - }, - { - "offset": 48, - "versions": [ - "1.8.0", - "1.8.2", - "1.9.0", - "1.9.1", - "1.9.2", - "1.10.0", - "1.10.1", - "1.11.0", - "1.11.1", - "1.11.2", - "1.11.3", - "1.12.0", - "1.12.1", - "1.12.2", - "1.13.0", - "1.14.0", "1.33.2", "1.33.3", + "1.34.0-dev", "1.34.0", "1.34.1", "1.34.2", @@ -2107,7 +1400,12 @@ "1.57.0", "1.57.1", "1.57.2", - "1.58.0-dev", + "1.58.0-dev" + ] + }, + { + "offset": 48, + "versions": [ "1.58.0", "1.58.1", "1.58.2", @@ -2128,6 +1426,7 @@ "1.63.1", "1.63.2", "1.63.3", + "1.64.0", "1.64.1", "1.65.0-dev", "1.65.0", @@ -2162,23 +1461,20 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] } ] - } - ] - }, - { - "package": "google.golang.org/grpc", - "structs": [ + }, { - "struct": "ClientConn", + "struct": "http2Client", "fields": [ { - "field": "target", + "field": "conn", "offsets": [ { "offset": null, @@ -2204,12 +1500,7 @@ "1.7.2", "1.7.3", "1.7.4", - "1.7.5" - ] - }, - { - "offset": 24, - "versions": [ + "1.7.5", "1.8.0", "1.8.2", "1.9.0", @@ -2224,7 +1515,12 @@ "1.12.0", "1.12.1", "1.12.2", - "1.13.0", + "1.13.0" + ] + }, + { + "offset": 64, + "versions": [ "1.14.0", "1.15.0", "1.16.0", @@ -2247,37 +1543,6 @@ "1.23.0", "1.23.1", "1.24.0", - "1.25.0", - "1.25.1", - "1.26.0", - "1.27.0-pre", - "1.27.0", - "1.27.1", - "1.28.0-pre", - "1.28.0", - "1.28.1", - "1.29.0-dev", - "1.29.0", - "1.29.1", - "1.30.0-dev", - "1.30.0-dev.1", - "1.30.0", - "1.30.1", - "1.31.0-dev", - "1.31.0", - "1.31.1", - "1.32.0-dev", - "1.32.0", - "1.33.0-dev", - "1.33.0", - "1.33.1", - "1.33.2", - "1.33.3", - "1.34.0-dev", - "1.34.0", - "1.34.1", - "1.34.2", - "1.35.0-dev", "1.35.0", "1.35.1", "1.36.0-dev", @@ -2321,27 +1586,48 @@ "1.50.1", "1.51.0-dev", "1.51.0", - "1.52.0-dev", - "1.52.0", - "1.52.1", - "1.52.3", - "1.53.0-dev", - "1.53.0", - "1.54.0", - "1.54.1", - "1.55.0-dev", - "1.55.0", - "1.55.1", - "1.56.0-dev", - "1.56.0", - "1.56.1", - "1.56.2", - "1.56.3", - "1.57.0-dev", - "1.57.0", - "1.57.1", - "1.57.2", - "1.58.0-dev", + "1.52.0-dev" + ] + }, + { + "offset": 72, + "versions": [ + "1.25.0", + "1.25.1", + "1.26.0", + "1.27.0-pre", + "1.27.0", + "1.27.1", + "1.28.0-pre", + "1.28.0", + "1.28.1", + "1.29.0-dev", + "1.29.0", + "1.29.1", + "1.30.0-dev", + "1.30.0-dev.1", + "1.30.0", + "1.30.1", + "1.31.0-dev", + "1.31.0", + "1.31.1", + "1.32.0-dev", + "1.32.0", + "1.33.0-dev", + "1.33.0", + "1.33.1", + "1.33.2", + "1.33.3", + "1.34.0-dev", + "1.34.0", + "1.34.1", + "1.34.2", + "1.35.0-dev" + ] + }, + { + "offset": 128, + "versions": [ "1.58.0", "1.58.1", "1.58.2", @@ -2397,23 +1683,45 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" + ] + }, + { + "offset": 136, + "versions": [ + "1.52.0", + "1.52.1", + "1.52.3", + "1.53.0-dev", + "1.53.0", + "1.54.0", + "1.54.1", + "1.55.0-dev", + "1.55.0", + "1.55.1", + "1.56.0-dev", + "1.56.0", + "1.56.1", + "1.56.2", + "1.56.3", + "1.57.0-dev", + "1.57.0", + "1.57.1", + "1.57.2", + "1.58.0-dev" ] } ] } ] - } - ] - }, - { - "package": "google.golang.org/grpc/internal/status", - "structs": [ + }, { - "struct": "Error", + "struct": "http2Server", "fields": [ { - "field": "s", + "field": "conn", "offsets": [ { "offset": null, @@ -2454,9 +1762,78 @@ "1.12.0", "1.12.1", "1.12.2", - "1.13.0", - "1.14.0", - "1.15.0", + "1.13.0" + ] + }, + { + "offset": 16, + "versions": [ + "1.60.0", + "1.60.1", + "1.61.0-dev", + "1.61.0", + "1.61.1", + "1.61.2", + "1.62.0", + "1.62.1", + "1.62.2", + "1.63.0", + "1.63.1", + "1.63.2", + "1.63.3", + "1.64.0", + "1.64.1", + "1.65.0-dev", + "1.65.0", + "1.65.1", + "1.66.0-dev", + "1.66.0", + "1.66.1", + "1.66.2", + "1.66.3", + "1.67.0-dev", + "1.67.0", + "1.67.1", + "1.67.2", + "1.67.3", + "1.68.0-dev", + "1.68.0", + "1.68.1", + "1.68.2", + "1.69.0-dev", + "1.69.0", + "1.69.2", + "1.69.4", + "1.70.0-dev", + "1.70.0", + "1.71.0-dev", + "1.71.0", + "1.71.1", + "1.71.2", + "1.71.3", + "1.72.0-dev", + "1.72.0", + "1.72.1", + "1.72.2", + "1.73.0-dev", + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" + ] + }, + { + "offset": 24, + "versions": [ + "1.24.0", + "1.25.0", + "1.25.1" + ] + }, + { + "offset": 32, + "versions": [ + "1.14.0", + "1.15.0", "1.16.0", "1.17.0", "1.18.0", @@ -2476,9 +1853,6 @@ "1.22.3", "1.23.0", "1.23.1", - "1.24.0", - "1.25.0", - "1.25.1", "1.26.0", "1.27.0-pre", "1.27.0", @@ -2522,12 +1896,7 @@ "1.39.0-dev", "1.39.0", "1.39.1", - "1.40.0-dev" - ] - }, - { - "offset": 0, - "versions": [ + "1.40.0-dev", "1.40.0", "1.40.1", "1.41.0-dev", @@ -2583,56 +1952,7 @@ "1.58.3", "1.59.0-dev", "1.59.0", - "1.60.0-dev", - "1.60.0", - "1.60.1", - "1.61.0-dev", - "1.61.0", - "1.61.1", - "1.61.2", - "1.62.0", - "1.62.1", - "1.62.2", - "1.63.0", - "1.63.1", - "1.63.2", - "1.63.3", - "1.64.0", - "1.64.1", - "1.65.0-dev", - "1.65.0", - "1.65.1", - "1.66.0-dev", - "1.66.0", - "1.66.1", - "1.66.2", - "1.66.3", - "1.67.0-dev", - "1.67.0", - "1.67.1", - "1.67.2", - "1.67.3", - "1.68.0-dev", - "1.68.0", - "1.68.1", - "1.68.2", - "1.69.0-dev", - "1.69.0", - "1.69.2", - "1.69.4", - "1.70.0-dev", - "1.70.0", - "1.71.0-dev", - "1.71.0", - "1.71.1", - "1.71.2", - "1.71.3", - "1.72.0-dev", - "1.72.0", - "1.72.1", - "1.72.2", - "1.73.0-dev", - "1.74.0-dev" + "1.60.0-dev" ] } ] @@ -2640,10 +1960,10 @@ ] }, { - "struct": "Status", + "struct": "loopyWriter", "fields": [ { - "field": "s", + "field": "framer", "offsets": [ { "offset": null, @@ -2684,7 +2004,12 @@ "1.12.0", "1.12.1", "1.12.2", - "1.13.0", + "1.13.0" + ] + }, + { + "offset": 40, + "versions": [ "1.14.0", "1.15.0", "1.16.0", @@ -2716,12 +2041,7 @@ "1.28.0-pre", "1.28.0", "1.28.1", - "1.29.0-dev" - ] - }, - { - "offset": 0, - "versions": [ + "1.29.0-dev", "1.29.0", "1.29.1", "1.30.0-dev", @@ -2862,26 +2182,26 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] } ] } - ] - }, - { - "package": "google.golang.org/grpc/internal/transport", - "structs": [ + ], + "funcs": [ { - "struct": "ServerStream", - "fields": [ + "func": "(*http2Client).operateHeaders", + "args": [ { - "field": "Stream", + "arg": "frame", "offsets": [ { "offset": null, + "location": "unknown", "versions": [ "1.0.0", "1.0.1-GA", @@ -2919,7 +2239,13 @@ "1.12.0", "1.12.1", "1.12.2", - "1.13.0", + "1.13.0" + ] + }, + { + "offset": 8, + "location": "registers", + "versions": [ "1.14.0", "1.15.0", "1.16.0", @@ -3076,12 +2402,7 @@ "1.68.0", "1.68.1", "1.68.2", - "1.69.0-dev" - ] - }, - { - "offset": 0, - "versions": [ + "1.69.0-dev", "1.69.0", "1.69.2", "1.69.4", @@ -3097,21 +2418,19 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] - } - ] - }, - { - "struct": "Stream", - "fields": [ + }, { - "field": "ctx", + "arg": "t", "offsets": [ { "offset": null, + "location": "unknown", "versions": [ "1.0.0", "1.0.1-GA", @@ -3153,28 +2472,8 @@ ] }, { - "offset": 8, - "versions": [ - "1.69.0", - "1.69.2", - "1.69.4", - "1.70.0-dev", - "1.70.0", - "1.71.0-dev", - "1.71.0", - "1.71.1", - "1.71.2", - "1.71.3", - "1.72.0-dev", - "1.72.0", - "1.72.1", - "1.72.2", - "1.73.0-dev", - "1.74.0-dev" - ] - }, - { - "offset": 24, + "offset": 0, + "location": "registers", "versions": [ "1.14.0", "1.15.0", @@ -3197,12 +2496,7 @@ "1.22.3", "1.23.0", "1.23.1", - "1.24.0" - ] - }, - { - "offset": 32, - "versions": [ + "1.24.0", "1.25.0", "1.25.1", "1.26.0", @@ -3323,12 +2617,7 @@ "1.65.0-dev", "1.65.0", "1.65.1", - "1.66.0-dev" - ] - }, - { - "offset": 40, - "versions": [ + "1.66.0-dev", "1.66.0", "1.66.1", "1.66.2", @@ -3342,16 +2631,40 @@ "1.68.0", "1.68.1", "1.68.2", - "1.69.0-dev" + "1.69.0-dev", + "1.69.0", + "1.69.2", + "1.69.4", + "1.70.0-dev", + "1.70.0", + "1.71.0-dev", + "1.71.0", + "1.71.1", + "1.71.2", + "1.71.3", + "1.72.0-dev", + "1.72.0", + "1.72.1", + "1.72.2", + "1.73.0-dev", + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] - }, + } + ] + }, + { + "func": "(*http2Server).operateHeaders", + "args": [ { - "field": "id", + "arg": "frame", "offsets": [ { "offset": null, + "location": "unknown", "versions": [ "1.0.0", "1.0.1-GA", @@ -3393,7 +2706,8 @@ ] }, { - "offset": 0, + "offset": 8, + "location": "registers", "versions": [ "1.14.0", "1.15.0", @@ -3518,7 +2832,13 @@ "1.58.3", "1.59.0-dev", "1.59.0", - "1.60.0-dev", + "1.60.0-dev" + ] + }, + { + "offset": 24, + "location": "registers", + "versions": [ "1.60.0", "1.60.1", "1.61.0-dev", @@ -3567,16 +2887,19 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] }, { - "field": "method", + "arg": "t", "offsets": [ { "offset": null, + "location": "unknown", "versions": [ "1.0.0", "1.0.1-GA", @@ -3618,28 +2941,8 @@ ] }, { - "offset": 24, - "versions": [ - "1.69.0", - "1.69.2", - "1.69.4", - "1.70.0-dev", - "1.70.0", - "1.71.0-dev", - "1.71.0", - "1.71.1", - "1.71.2", - "1.71.3", - "1.72.0-dev", - "1.72.0", - "1.72.1", - "1.72.2", - "1.73.0-dev", - "1.74.0-dev" - ] - }, - { - "offset": 64, + "offset": 0, + "location": "registers", "versions": [ "1.14.0", "1.15.0", @@ -3662,12 +2965,7 @@ "1.22.3", "1.23.0", "1.23.1", - "1.24.0" - ] - }, - { - "offset": 72, - "versions": [ + "1.24.0", "1.25.0", "1.25.1", "1.26.0", @@ -3704,12 +3002,7 @@ "1.36.0-dev", "1.36.0", "1.36.1", - "1.37.0-dev" - ] - }, - { - "offset": 80, - "versions": [ + "1.37.0-dev", "1.37.0", "1.37.1", "1.38.0-dev", @@ -3793,12 +3086,7 @@ "1.65.0-dev", "1.65.0", "1.65.1", - "1.66.0-dev" - ] - }, - { - "offset": 88, - "versions": [ + "1.66.0-dev", "1.66.0", "1.66.1", "1.66.2", @@ -3812,7 +3100,25 @@ "1.68.0", "1.68.1", "1.68.2", - "1.69.0-dev" + "1.69.0-dev", + "1.69.0", + "1.69.2", + "1.69.4", + "1.70.0-dev", + "1.70.0", + "1.71.0-dev", + "1.71.0", + "1.71.1", + "1.71.2", + "1.71.3", + "1.72.0-dev", + "1.72.0", + "1.72.1", + "1.72.2", + "1.73.0-dev", + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] @@ -3820,13 +3126,14 @@ ] }, { - "struct": "headerFrame", - "fields": [ + "func": "(*loopyWriter).writeHeader", + "args": [ { - "field": "hf", + "arg": "endStream", "offsets": [ { "offset": null, + "location": "unknown", "versions": [ "1.0.0", "1.0.1-GA", @@ -3868,7 +3175,8 @@ ] }, { - "offset": 8, + "offset": 16, + "location": "registers", "versions": [ "1.14.0", "1.15.0", @@ -4042,16 +3350,19 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] }, { - "field": "streamID", + "arg": "hf", "offsets": [ { "offset": null, + "location": "unknown", "versions": [ "1.0.0", "1.0.1-GA", @@ -4093,7 +3404,8 @@ ] }, { - "offset": 0, + "offset": 24, + "location": "registers", "versions": [ "1.14.0", "1.15.0", @@ -4267,21 +3579,19 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] - } - ] - }, - { - "struct": "http2Client", - "fields": [ + }, { - "field": "nextID", + "arg": "l", "offsets": [ { "offset": null, + "location": "unknown", "versions": [ "1.0.0", "1.0.1-GA", @@ -4323,8 +3633,62 @@ ] }, { - "offset": 340, + "offset": 0, + "location": "registers", "versions": [ + "1.14.0", + "1.15.0", + "1.16.0", + "1.17.0", + "1.18.0", + "1.18.1", + "1.19.0", + "1.19.1", + "1.20.0", + "1.20.1", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.22.0", + "1.22.1", + "1.22.2", + "1.22.3", + "1.23.0", + "1.23.1", + "1.24.0", + "1.25.0", + "1.25.1", + "1.26.0", + "1.27.0-pre", + "1.27.0", + "1.27.1", + "1.28.0-pre", + "1.28.0", + "1.28.1", + "1.29.0-dev", + "1.29.0", + "1.29.1", + "1.30.0-dev", + "1.30.0-dev.1", + "1.30.0", + "1.30.1", + "1.31.0-dev", + "1.31.0", + "1.31.1", + "1.32.0-dev", + "1.32.0", + "1.33.0-dev", + "1.33.0", + "1.33.1", + "1.33.2", + "1.33.3", + "1.34.0-dev", + "1.34.0", + "1.34.1", + "1.34.2", + "1.35.0-dev", "1.35.0", "1.35.1", "1.36.0-dev", @@ -4360,108 +3724,15 @@ "1.47.0-dev", "1.47.0", "1.48.0-dev", - "1.51.0", - "1.52.0-dev" - ] - }, - { - "offset": 348, - "versions": [ - "1.24.0", - "1.25.0", - "1.25.1", - "1.26.0", - "1.27.0-pre", - "1.27.0", - "1.27.1", - "1.28.0-pre", - "1.28.0", - "1.28.1", - "1.29.0-dev", - "1.29.0", - "1.29.1", - "1.30.0-dev", - "1.30.0-dev.1", - "1.30.0", - "1.30.1", - "1.31.0-dev", - "1.31.0", - "1.31.1", - "1.32.0-dev", - "1.32.0", - "1.33.0-dev", - "1.33.0", - "1.33.1", - "1.33.2", - "1.33.3", - "1.34.0-dev", - "1.34.0", - "1.34.1", - "1.34.2", - "1.35.0-dev", "1.48.0", "1.49.0-dev", "1.49.0", "1.50.0-dev", "1.50.0", "1.50.1", - "1.51.0-dev" - ] - }, - { - "offset": 356, - "versions": [ - "1.14.0", - "1.15.0", - "1.16.0", - "1.17.0", - "1.18.0", - "1.18.1", - "1.19.0", - "1.19.1", - "1.20.0", - "1.20.1", - "1.21.0", - "1.21.1", - "1.21.2", - "1.21.3", - "1.21.4", - "1.22.0", - "1.22.1", - "1.22.2", - "1.22.3", - "1.23.0", - "1.23.1" - ] - }, - { - "offset": 404, - "versions": [ - "1.58.0", - "1.58.1", - "1.58.2", - "1.58.3", - "1.59.0-dev", - "1.59.0", - "1.60.0-dev", - "1.60.0", - "1.60.1", - "1.61.0-dev", - "1.61.0", - "1.61.1", - "1.61.2", - "1.62.0", - "1.62.1", - "1.62.2", - "1.63.0", - "1.63.1", - "1.63.2", - "1.63.3" - ] - }, - { - "offset": 412, - "versions": [ + "1.51.0-dev", + "1.51.0", + "1.52.0-dev", "1.52.0", "1.52.1", "1.52.3", @@ -4481,12 +3752,27 @@ "1.57.0", "1.57.1", "1.57.2", - "1.58.0-dev" - ] - }, - { - "offset": 432, - "versions": [ + "1.58.0-dev", + "1.58.0", + "1.58.1", + "1.58.2", + "1.58.3", + "1.59.0-dev", + "1.59.0", + "1.60.0-dev", + "1.60.0", + "1.60.1", + "1.61.0-dev", + "1.61.0", + "1.61.1", + "1.61.2", + "1.62.0", + "1.62.1", + "1.62.2", + "1.63.0", + "1.63.1", + "1.63.2", + "1.63.3", "1.64.0", "1.64.1", "1.65.0-dev", @@ -4502,12 +3788,7 @@ "1.67.1", "1.67.2", "1.67.3", - "1.68.0-dev" - ] - }, - { - "offset": 440, - "versions": [ + "1.68.0-dev", "1.68.0", "1.68.1", "1.68.2", @@ -4527,21 +3808,19 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] - } - ] - }, - { - "struct": "http2Server", - "fields": [ + }, { - "field": "peer", + "arg": "streamID", "offsets": [ { "offset": null, + "location": "unknown", "versions": [ "1.0.0", "1.0.1-GA", @@ -4579,7 +3858,13 @@ "1.12.0", "1.12.1", "1.12.2", - "1.13.0", + "1.13.0" + ] + }, + { + "offset": 8, + "location": "registers", + "versions": [ "1.14.0", "1.15.0", "1.16.0", @@ -4703,12 +3988,7 @@ "1.58.3", "1.59.0-dev", "1.59.0", - "1.60.0-dev" - ] - }, - { - "offset": 56, - "versions": [ + "1.60.0-dev", "1.60.0", "1.60.1", "1.61.0-dev", @@ -4757,7 +4037,9 @@ "1.72.1", "1.72.2", "1.73.0-dev", - "1.74.0-dev" + "1.73.0", + "1.74.0-dev", + "1.75.0-dev" ] } ] @@ -4765,258 +4047,362 @@ ] } ] - }, + } + ] + }, + { + "module": "std", + "packages": [ { - "package": "google.golang.org/grpc/peer", + "package": "crypto/tls", "structs": [ { - "struct": "Peer", + "struct": "Conn", "fields": [ { - "field": "LocalAddr", + "field": "conn", "offsets": [ { - "offset": null, + "offset": 0, "versions": [ - "1.0.0", - "1.0.1-GA", - "1.0.2", - "1.0.3", - "1.0.4", - "1.0.5", - "1.2.0", - "1.2.1", - "1.3.0", - "1.4.0", - "1.4.1", - "1.4.2", - "1.5.0", - "1.5.1", - "1.5.2", - "1.6.0", - "1.7.0", - "1.7.1", - "1.7.2", - "1.7.3", - "1.7.4", - "1.7.5", - "1.8.0", - "1.8.2", - "1.9.0", - "1.9.1", - "1.9.2", - "1.10.0", - "1.10.1", - "1.11.0", - "1.11.1", - "1.11.2", - "1.11.3", - "1.12.0", - "1.12.1", - "1.12.2", - "1.13.0", - "1.14.0", - "1.15.0", - "1.16.0", - "1.17.0", - "1.18.0", - "1.18.1", "1.19.0", "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", "1.20.0", "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", "1.21.0", "1.21.1", "1.21.2", "1.21.3", "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9", + "1.21.10", + "1.21.11", + "1.21.12", + "1.21.13", "1.22.0", "1.22.1", "1.22.2", "1.22.3", + "1.22.4", + "1.22.5", + "1.22.6", + "1.22.7", + "1.22.8", + "1.22.9", + "1.22.10", + "1.22.11", + "1.22.12", "1.23.0", "1.23.1", + "1.23.2", + "1.23.3", + "1.23.4", + "1.23.5", + "1.23.6", + "1.23.7", + "1.23.8", + "1.23.9", + "1.23.10", "1.24.0", - "1.25.0", - "1.25.1", - "1.26.0", - "1.27.0-pre", - "1.27.0", - "1.27.1", - "1.28.0-pre", - "1.28.0", - "1.28.1", - "1.29.0-dev", - "1.29.0", - "1.29.1", - "1.30.0-dev", - "1.30.0-dev.1", - "1.30.0", - "1.30.1", - "1.31.0-dev", - "1.31.0", - "1.31.1", - "1.32.0-dev", - "1.32.0", - "1.33.0-dev", - "1.33.0", - "1.33.1", - "1.33.2", - "1.33.3", - "1.34.0-dev", - "1.34.0", - "1.34.1", - "1.34.2", - "1.35.0-dev", - "1.35.0", - "1.35.1", - "1.36.0-dev", - "1.36.0", - "1.36.1", - "1.37.0-dev", - "1.37.0", - "1.37.1", - "1.38.0-dev", - "1.38.0", - "1.38.1", - "1.39.0-dev", - "1.39.0", - "1.39.1", - "1.40.0-dev", - "1.40.0", - "1.40.1", - "1.41.0-dev", - "1.41.0", - "1.41.1", - "1.42.0-dev", - "1.42.0", - "1.43.0-dev", - "1.43.0", - "1.44.0-dev", - "1.44.0", - "1.45.0-dev", - "1.45.0", - "1.46.0-dev", - "1.46.0", - "1.46.1", - "1.46.2", - "1.47.0-dev", - "1.47.0", - "1.48.0-dev", - "1.48.0", - "1.49.0-dev", - "1.49.0", - "1.50.0-dev", - "1.50.0", - "1.50.1", - "1.51.0-dev", - "1.51.0", - "1.52.0-dev", - "1.52.0", - "1.52.1", - "1.52.3", - "1.53.0-dev", - "1.53.0", - "1.54.0", - "1.54.1", - "1.55.0-dev", - "1.55.0", - "1.55.1", - "1.56.0-dev", - "1.56.0", - "1.56.1", - "1.56.2", - "1.56.3", - "1.57.0-dev", - "1.57.0", - "1.57.1", - "1.57.2", - "1.58.0-dev", - "1.58.0", - "1.58.1", - "1.58.2", - "1.58.3", - "1.59.0-dev", - "1.59.0", - "1.60.0-dev" + "1.24.1", + "1.24.2", + "1.24.3", + "1.24.4" ] - }, + } + ] + } + ] + } + ], + "funcs": [ + { + "func": "(*Conn).Read", + "args": [ + { + "arg": "b", + "offsets": [ { - "offset": 16, + "offset": 8, + "location": "registers", "versions": [ - "1.60.0", - "1.60.1", - "1.61.0-dev", - "1.61.0", - "1.61.1", - "1.61.2", - "1.62.0", - "1.62.1", - "1.62.2", - "1.63.0", - "1.63.1", - "1.63.2", - "1.63.3", - "1.64.0", - "1.64.1", - "1.65.0-dev", - "1.65.0", - "1.65.1", - "1.66.0-dev", - "1.66.0", - "1.66.1", - "1.66.2", - "1.66.3", - "1.67.0-dev", - "1.67.0", - "1.67.1", - "1.67.2", - "1.67.3", - "1.68.0-dev", - "1.68.0", - "1.68.1", - "1.68.2", - "1.69.0-dev", - "1.69.0", - "1.69.2", - "1.69.4", - "1.70.0-dev", - "1.70.0", - "1.71.0-dev", - "1.71.0", - "1.71.1", - "1.71.2", - "1.71.3", - "1.72.0-dev", - "1.72.0", - "1.72.1", - "1.72.2", - "1.73.0-dev", - "1.74.0-dev" + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9", + "1.21.10", + "1.21.11", + "1.21.12", + "1.21.13", + "1.22.0", + "1.22.1", + "1.22.2", + "1.22.3", + "1.22.4", + "1.22.5", + "1.22.6", + "1.22.7", + "1.22.8", + "1.22.9", + "1.22.10", + "1.22.11", + "1.22.12", + "1.23.0", + "1.23.1", + "1.23.2", + "1.23.3", + "1.23.4", + "1.23.5", + "1.23.6", + "1.23.7", + "1.23.8", + "1.23.9", + "1.23.10", + "1.24.0", + "1.24.1", + "1.24.2", + "1.24.3", + "1.24.4" + ] + } + ] + }, + { + "arg": "c", + "offsets": [ + { + "offset": 0, + "location": "registers", + "versions": [ + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9", + "1.21.10", + "1.21.11", + "1.21.12", + "1.21.13", + "1.22.0", + "1.22.1", + "1.22.2", + "1.22.3", + "1.22.4", + "1.22.5", + "1.22.6", + "1.22.7", + "1.22.8", + "1.22.9", + "1.22.10", + "1.22.11", + "1.22.12", + "1.23.0", + "1.23.1", + "1.23.2", + "1.23.3", + "1.23.4", + "1.23.5", + "1.23.6", + "1.23.7", + "1.23.8", + "1.23.9", + "1.23.10", + "1.24.0", + "1.24.1", + "1.24.2", + "1.24.3", + "1.24.4" + ] + } + ] + }, + { + "arg": "~r0", + "offsets": [ + { + "offset": 0, + "location": "registers", + "versions": [ + "1.19.0", + "1.19.1", + "1.19.2", + "1.19.3", + "1.19.4", + "1.19.5", + "1.19.6", + "1.19.7", + "1.19.8", + "1.19.9", + "1.19.10", + "1.19.11", + "1.19.12", + "1.19.13", + "1.20.0", + "1.20.1", + "1.20.2", + "1.20.3", + "1.20.4", + "1.20.5", + "1.20.6", + "1.20.7", + "1.20.8", + "1.20.9", + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14", + "1.21.0", + "1.21.1", + "1.21.2", + "1.21.3", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9", + "1.21.10", + "1.21.11", + "1.21.12", + "1.21.13", + "1.22.0", + "1.22.1", + "1.22.2", + "1.22.3", + "1.22.4", + "1.22.5", + "1.22.6", + "1.22.7", + "1.22.8", + "1.22.9", + "1.22.10", + "1.22.11", + "1.22.12", + "1.23.0", + "1.23.1", + "1.23.2", + "1.23.3", + "1.23.4", + "1.23.5", + "1.23.6", + "1.23.7", + "1.23.8", + "1.23.9", + "1.23.10", + "1.24.0", + "1.24.1", + "1.24.2", + "1.24.3", + "1.24.4" ] } ] - } - ] - } - ] - } - ] - }, - { - "module": "std", - "packages": [ - { - "package": "bufio", - "structs": [ - { - "struct": "Writer", - "fields": [ + }, { - "field": "buf", + "arg": "~r1", "offsets": [ { - "offset": 16, + "offset": 8, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -5084,19 +4470,27 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + }, + { + "func": "(*Conn).Write", + "args": [ { - "field": "n", + "arg": "b", "offsets": [ { - "offset": 40, + "offset": 8, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -5164,29 +4558,22 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - } - ] - } - ] - }, - { - "package": "net", - "structs": [ - { - "struct": "TCPAddr", - "fields": [ + }, { - "field": "IP", + "arg": "c", "offsets": [ { "offset": 0, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -5254,19 +4641,22 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "Port", + "arg": "~r0", "offsets": [ { - "offset": 24, + "offset": 0, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -5334,29 +4724,22 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - } - ] - } - ] - }, - { - "package": "net/http", - "structs": [ - { - "struct": "Request", - "fields": [ + }, { - "field": "Header", + "arg": "~r1", "offsets": [ { - "offset": 56, + "offset": 8, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -5424,19 +4807,31 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + } + ] + }, + { + "package": "internal/poll", + "structs": [ + { + "struct": "FD", + "fields": [ { - "field": "Host", + "field": "Sysfd", "offsets": [ { - "offset": 128, + "offset": 16, "versions": [ "1.19.0", "1.19.1", @@ -5504,19 +4899,32 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + } + ], + "funcs": null + }, + { + "package": "net/http", + "structs": [ + { + "struct": "http2DataFrame", + "fields": [ { - "field": "Method", + "field": "data", "offsets": [ { - "offset": 0, + "offset": 16, "versions": [ "1.19.0", "1.19.1", @@ -5584,19 +4992,26 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + }, + { + "struct": "http2FrameHeader", + "fields": [ { - "field": "Pattern", + "field": "Flags", "offsets": [ { - "offset": null, + "offset": 2, "versions": [ "1.19.0", "1.19.1", @@ -5653,12 +5068,7 @@ "1.22.9", "1.22.10", "1.22.11", - "1.22.12" - ] - }, - { - "offset": 232, - "versions": [ + "1.22.12", "1.23.0", "1.23.1", "1.23.2", @@ -5669,19 +5079,21 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "Proto", + "field": "StreamID", "offsets": [ { - "offset": 24, + "offset": 8, "versions": [ "1.19.0", "1.19.1", @@ -5749,19 +5161,21 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "RemoteAddr", + "field": "Type", "offsets": [ { - "offset": 176, + "offset": 1, "versions": [ "1.19.0", "1.19.1", @@ -5829,19 +5243,26 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + }, + { + "struct": "http2Framer", + "fields": [ { - "field": "RequestURI", + "field": "w", "offsets": [ { - "offset": 192, + "offset": 120, "versions": [ "1.19.0", "1.19.1", @@ -5909,19 +5330,26 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + }, + { + "struct": "http2HeadersFrame", + "fields": [ { - "field": "URL", + "field": "http2FrameHeader", "offsets": [ { - "offset": 16, + "offset": 0, "versions": [ "1.19.0", "1.19.1", @@ -5989,19 +5417,26 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + }, + { + "struct": "http2MetaHeadersFrame", + "fields": [ { - "field": "ctx", + "field": "Fields", "offsets": [ { - "offset": 232, + "offset": 8, "versions": [ "1.19.0", "1.19.1", @@ -6058,12 +5493,7 @@ "1.22.9", "1.22.10", "1.22.11", - "1.22.12" - ] - }, - { - "offset": 248, - "versions": [ + "1.22.12", "1.23.0", "1.23.1", "1.23.2", @@ -6074,19 +5504,21 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "pat", + "field": "http2HeadersFrame", "offsets": [ { - "offset": null, + "offset": 0, "versions": [ "1.19.0", "1.19.1", @@ -6130,12 +5562,7 @@ "1.21.10", "1.21.11", "1.21.12", - "1.21.13" - ] - }, - { - "offset": 248, - "versions": [ + "1.21.13", "1.22.0", "1.22.1", "1.22.2", @@ -6148,12 +5575,7 @@ "1.22.9", "1.22.10", "1.22.11", - "1.22.12" - ] - }, - { - "offset": 264, - "versions": [ + "1.22.12", "1.23.0", "1.23.1", "1.23.2", @@ -6164,10 +5586,12 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] @@ -6175,13 +5599,13 @@ ] }, { - "struct": "Response", + "struct": "http2bufferedWriter", "fields": [ { - "field": "StatusCode", + "field": "conn", "offsets": [ { - "offset": 16, + "offset": null, "versions": [ "1.19.0", "1.19.1", @@ -6249,24 +5673,36 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10" + ] + }, + { + "offset": 16, + "versions": [ "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - } - ] - }, - { - "struct": "pattern", - "fields": [ + }, { - "field": "str", + "field": "w", "offsets": [ { "offset": null, + "versions": [ + "1.24.0", + "1.24.1", + "1.24.2", + "1.24.3", + "1.24.4" + ] + }, + { + "offset": 0, "versions": [ "1.19.0", "1.19.1", @@ -6310,12 +5746,7 @@ "1.21.10", "1.21.11", "1.21.12", - "1.21.13" - ] - }, - { - "offset": 0, - "versions": [ + "1.21.13", "1.22.0", "1.22.1", "1.22.2", @@ -6339,10 +5770,7 @@ "1.23.7", "1.23.8", "1.23.9", - "1.24.0", - "1.24.1", - "1.24.2", - "1.24.3" + "1.23.10" ] } ] @@ -6350,13 +5778,13 @@ ] }, { - "struct": "response", + "struct": "http2serverConn", "fields": [ { - "field": "req", + "field": "conn", "offsets": [ { - "offset": 8, + "offset": 16, "versions": [ "1.19.0", "1.19.1", @@ -6424,24 +5852,34 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "status", + "field": "hpackEncoder", "offsets": [ { - "offset": 120, + "offset": 360, "versions": [ "1.19.0", "1.19.1", "1.19.2", "1.19.3", + "1.21.0", + "1.21.1", + "1.21.2" + ] + }, + { + "offset": 368, + "versions": [ "1.19.4", "1.19.5", "1.19.6", @@ -6461,15 +5899,12 @@ "1.20.6", "1.20.7", "1.20.8", - "1.20.9", - "1.20.10", - "1.20.11", - "1.20.12", - "1.20.13", - "1.20.14", - "1.21.0", - "1.21.1", - "1.21.2", + "1.20.9" + ] + }, + { + "offset": 392, + "versions": [ "1.21.3", "1.21.4", "1.21.5", @@ -6493,7 +5928,22 @@ "1.22.9", "1.22.10", "1.22.11", - "1.22.12", + "1.22.12" + ] + }, + { + "offset": 400, + "versions": [ + "1.20.10", + "1.20.11", + "1.20.12", + "1.20.13", + "1.20.14" + ] + }, + { + "offset": 408, + "versions": [ "1.23.0", "1.23.1", "1.23.2", @@ -6504,29 +5954,31 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10" + ] + }, + { + "offset": 456, + "versions": [ "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] } ] - } - ] - }, - { - "package": "net/url", - "structs": [ + }, { - "struct": "URL", + "struct": "http2writeResHeaders", "fields": [ { - "field": "ForceQuery", + "field": "endStream", "offsets": [ { - "offset": 89, + "offset": 48, "versions": [ "1.19.0", "1.19.1", @@ -6594,19 +6046,21 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "Fragment", + "field": "streamID", "offsets": [ { - "offset": 112, + "offset": 0, "versions": [ "1.19.0", "1.19.1", @@ -6674,19 +6128,29 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + } + ], + "funcs": [ + { + "func": "(*http2Framer).WriteDataPadded", + "args": [ { - "field": "Host", + "arg": "data", "offsets": [ { - "offset": 40, + "offset": 24, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -6754,19 +6218,22 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "OmitHost", + "arg": "endStream", "offsets": [ { - "offset": 88, + "offset": 16, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -6834,19 +6301,22 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "Opaque", + "arg": "f", "offsets": [ { - "offset": 16, + "offset": 0, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -6914,19 +6384,22 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "Path", + "arg": "streamID", "offsets": [ { - "offset": 56, + "offset": 8, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -6994,19 +6467,27 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + }, + { + "func": "(*http2Framer).checkFrameOrder", + "args": [ { - "field": "RawFragment", + "arg": "f", "offsets": [ { - "offset": 128, + "offset": 8, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -7074,19 +6555,22 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "RawPath", + "arg": "fr", "offsets": [ { - "offset": 72, + "offset": 0, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -7154,19 +6638,27 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + }, + { + "func": "(*http2serverConn).processHeaders", + "args": [ { - "field": "RawQuery", + "arg": "f", "offsets": [ { - "offset": 96, + "offset": 8, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -7234,19 +6726,22 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] }, { - "field": "Scheme", + "arg": "sc", "offsets": [ { "offset": 0, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -7314,19 +6809,27 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - }, + } + ] + }, + { + "func": "(*http2writeResHeaders).writeFrame", + "args": [ { - "field": "User", + "arg": "ctx", "offsets": [ { - "offset": 32, + "offset": 8, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -7394,24 +6897,22 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] - } - ] - }, - { - "struct": "Userinfo", - "fields": [ + }, { - "field": "username", + "arg": "w", "offsets": [ { "offset": 0, + "location": "registers", "versions": [ "1.19.0", "1.19.1", @@ -7479,10 +6980,12 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] @@ -7574,10 +7077,12 @@ "1.23.7", "1.23.8", "1.23.9", + "1.23.10", "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] } ] @@ -7596,7 +7101,8 @@ "1.24.0", "1.24.1", "1.24.2", - "1.24.3" + "1.24.3", + "1.24.4" ] }, { @@ -7667,14 +7173,16 @@ "1.23.6", "1.23.7", "1.23.8", - "1.23.9" + "1.23.9", + "1.23.10" ] } ] } ] } - ] + ], + "funcs": null } ] } diff --git a/internal/pkg/process/dwarf.go b/internal/pkg/process/dwarf.go index d6ba7e5a69..e95c0710f4 100644 --- a/internal/pkg/process/dwarf.go +++ b/internal/pkg/process/dwarf.go @@ -8,21 +8,418 @@ import ( "errors" "fmt" "io" + "log" + "slices" + "strings" + "go.opentelemetry.io/auto/internal/pkg/funcfield" "go.opentelemetry.io/auto/internal/pkg/structfield" ) // ErrDWARFEntry is returned if an entry is not found within DWARF data. var ErrDWARFEntry = errors.New("DWARF entry not found") -// DWARF provides convenience in accessing DWARF debugging data. -type DWARF struct { - Reader *dwarf.Reader +type ABI int + +const ( + AbiUnknown ABI = iota + AbiGoStack ABI = iota + AbiGoReg ABI = iota +) + +type ArgTracker interface { + PopLocation(typeClass TypeClass, typeSize uint64, alignmentSize uint64, numVars int, retArg bool) (FuncFieldArg, error) +} + +// NewArgTracker returns an ArgTracker based on the ABI. +func NewArgTracker(abi ABI, addrSize int) ArgTracker { + if abi == AbiGoReg { + return &GoRegABIArgTracker{ + CurrentStackOffset: 0, + AddrSize: addrSize, + IntArgRegs: []Registers{kRAX, kRBX, kRCX, kRDX, kRSI, kR8, kR9, kR10, kR11}, + IntRetValRegs: []Registers{kRAX, kRBX, kRCX, kRDX, kRSI, kR8, kR9, kR10, kR11}, + FloatArgRegs: []Registers{kXMM0, kXMM1, kXMM2, kXMM3, kXMM4, kXMM5, kXMM6, kXMM7, kXMM8, kXMM9, kXMM10, kXMM11, kXMM12, kXMM13, kXMM14}, + FloatRetValRegs: []Registers{kXMM0, kXMM1, kXMM2, kXMM3, kXMM4, kXMM5, kXMM6, kXMM7, kXMM8, kXMM9, kXMM10, kXMM11, kXMM12, kXMM13, kXMM14}, + } + } else if abi == AbiGoStack { + return &GoStackABIArgTracker{ + CurrentStackOffset: 0, + AddrSize: addrSize, + } + } else { + return nil + } +} + +type Registers int + +const ( + kRAX = 0 + kRBX = 1 + kRCX = 2 + kRDX = 3 + kRDI = 4 + kRSI = 5 + kR8 = 6 + kR9 = 7 + kR10 = 8 + kR11 = 9 + + kXMM0 = 100 + kXMM1 = 101 + kXMM2 = 102 + kXMM3 = 103 + kXMM4 = 104 + kXMM5 = 105 + kXMM6 = 106 + kXMM7 = 107 + kXMM8 = 108 + kXMM9 = 109 + kXMM10 = 110 + kXMM11 = 111 + kXMM12 = 112 + kXMM13 = 113 + kXMM14 = 114 +) + +type GoRegABIArgTracker struct { + AddrSize int + CurrentStackOffset uint64 + CurrentIntRegOffset uint64 + CurrentFloatRegOffset uint64 + CurrentIntRetValOffset uint64 + CurrentFloatRetValOffset uint64 + + RegisterSize uint64 + IntArgRegs []Registers + FloatArgRegs []Registers + IntRetValRegs []Registers + FloatRetValRegs []Registers +} + +func (g *GoRegABIArgTracker) PopLocation(typeClass TypeClass, typeSize uint64, alignmentSize uint64, numVars int, retArg bool) (FuncFieldArg, error) { + var regOffset *uint64 + var registers *[]Registers + if typeClass == TypeClassInt { + if retArg { + registers = &g.IntRetValRegs + regOffset = &g.CurrentIntRetValOffset + } else { + registers = &g.IntArgRegs + regOffset = &g.CurrentIntRegOffset + } + } else if typeClass == TypeClassFloat { + if retArg { + registers = &g.FloatRetValRegs + regOffset = &g.CurrentFloatRetValOffset + } else { + registers = &g.FloatArgRegs + regOffset = &g.CurrentFloatRegOffset + } + } + funcFieldArg := FuncFieldArg{ + RetArg: retArg, + } + if numVars <= len(*registers) { + funcFieldArg.Location = funcfield.Registers + funcFieldArg.Offset = *regOffset + + // TODO(ddelnano): Consider if its worth tracking which registers belong + // to a funcFieldArg. This is done in Pixie's implementation, but is not required + // for this uprobe optimization feature set. + + // Pop a register off for each variable in the type. + for i := 0; i < numVars; i++ { + *registers = (*registers)[1:] + } + *regOffset += uint64(numVars * g.AddrSize) + return funcFieldArg, nil + } else { + funcFieldArg.Location = funcfield.Stack + return funcFieldArg, errors.New("Stack arguments not implemented for GoRegABIArgTracker") + } +} + +type GoStackABIArgTracker struct { + AddrSize int + CurrentStackOffset uint64 +} + +func IntRoundDivide(x uint64, y uint64) uint64 { + return (x + (y - 1)) / y +} + +func SnapUpToMultiple(x, y uint64) uint64 { + return IntRoundDivide(x, y) * y +} + +// TODO(ddelnano): This is yet to be tested. As upstream has never supported these binaries. +func (g *GoStackABIArgTracker) PopLocation(typeClass TypeClass, typeSize uint64, alignmentSize uint64, numVars int, retArg bool) (FuncFieldArg, error) { + + g.CurrentStackOffset = SnapUpToMultiple(g.CurrentStackOffset, alignmentSize) + offset := g.CurrentStackOffset + g.CurrentStackOffset += typeSize + return FuncFieldArg{ + RetArg: retArg, + Offset: offset, + Location: funcfield.Stack, + }, nil +} + +// typeInfo stores pre-computed properties for a DWARF type node. +type typeInfo struct { + size uint64 + align uint64 + class TypeClass + nVars int +} + +type DWARF interface { + GoFuncFieldArgs(fn string) (map[string]FuncFieldArg, error) + GoStructField(id structfield.ID) (int64, error) +} + +func NewDWARF(d *dwarf.Data) DWARF { + return dwarfReader{ + Data: d, + Reader: d.Reader(), + typeCache: make(map[dwarf.Offset]typeInfo), + } +} + +// dwarfReader provides convenience in accessing DWARF debugging data. +type dwarfReader struct { + Data *dwarf.Data + Reader *dwarf.Reader + argTracker ArgTracker + typeCache map[dwarf.Offset]typeInfo +} + +type FuncFieldArg struct { + Offset uint64 `json:"offset"` + Location funcfield.Location `json:"location"` + RetArg bool `json:"ret_arg"` // true if this is a return argument +} + +func (d dwarfReader) DetectSourceABI() (ABI, error) { + cus, err := d.EntriesWithTag(dwarf.TagCompileUnit) + if err != nil || len(cus) == 0 { + return AbiUnknown, fmt.Errorf("No compile units found") + } + abi := AbiUnknown + for _, cu := range cus { + cuProducer, ok := d.Field(cu, dwarf.AttrProducer) + if !ok { + continue + } + producer, ok := cuProducer.Val.(string) + if strings.Contains(producer, "regabi") { + abi = AbiGoReg + } else { + abi = AbiGoStack + } + } + if abi == AbiUnknown { + return abi, fmt.Errorf("didn't find a AT_producer in any compile unit") + } + return abi, nil +} + +func (d dwarfReader) IsRetArg(die *dwarf.Entry) bool { + if f, ok := d.Field(die, dwarf.AttrVarParam); ok { + varParam := f.Val.(bool) + return varParam + } + return false +} + +func (d dwarfReader) GetTypeDIE(entry *dwarf.Entry) (*dwarf.Entry, error) { + var field dwarf.Field + var found bool + var err error + for { + field, found = d.Field(entry, dwarf.AttrType) + if !found { + return nil, fmt.Errorf("failed to get type attribute: %w", ErrDWARFEntry) + } + typeOffset, ok := field.Val.(dwarf.Offset) + if !ok { + return nil, fmt.Errorf("type attribute is not a valid dwarf.Offset: %w", ErrDWARFEntry) + } + d.Reader.Seek(typeOffset) + entry, err = d.Reader.Next() + if errors.Is(err, io.EOF) || entry == nil || entry.Tag == 0 { + return nil, ErrDWARFEntry + } + if entry.Tag != dwarf.TagTypedef { + return entry, nil + } + } + return nil, ErrDWARFEntry +} + +type TypeClass int + +const ( + TypeClassNone TypeClass = iota + TypeClassInt TypeClass = iota + TypeClassFloat TypeClass = iota + TypeClassMixed TypeClass = iota +) + +func combineTypeClasses(a, b TypeClass) TypeClass { + if a == TypeClassMixed || b == TypeClassMixed { + return TypeClassMixed + } + if b == TypeClassNone { + return a + } + if a == TypeClassNone { + return b + } + + if a != TypeClassInt && a != TypeClassFloat { + panic(fmt.Sprintf("invalid type class: %v", a)) + } + if b != TypeClassInt && b != TypeClassFloat { + panic(fmt.Sprintf("invalid type class: %v", b)) + } + + if a != b { + return TypeClassMixed + } + return a +} + +func (d *dwarfReader) getTypeInfo(t dwarf.Type) (typeInfo, error) { + var ti typeInfo + + switch tt := t.(type) { + case *dwarf.PtrType, *dwarf.BoolType, *dwarf.FuncType, + *dwarf.IntType, *dwarf.UintType: + sz := uint64(tt.Size()) + ti = typeInfo{ + size: sz, + align: sz, + class: TypeClassInt, + nVars: 1, + } + + case *dwarf.TypedefType: + return d.getTypeInfo(tt.Type) + case *dwarf.FloatType: + sz := uint64(tt.Size()) + ti = typeInfo{ + size: sz, + align: sz, + class: TypeClassFloat, + nVars: 1, + } + + case *dwarf.StructType: + ti.class = TypeClassNone + for _, f := range tt.Field { + sub, err := d.getTypeInfo(f.Type) + if err != nil { + return typeInfo{}, err + } + // Size must cover the highest field end. + end := uint64(f.ByteOffset) + sub.size + ti.size = max(ti.size, end) + ti.align = max(ti.align, sub.align) + ti.nVars += sub.nVars + ti.class = combineTypeClasses(ti.class, sub.class) + } + if ti.class == TypeClassNone { + ti.class = TypeClassMixed + } + + default: + return typeInfo{}, fmt.Errorf("unsupported dwarf.Type %T", tt) + } + + if ti.align == 0 { + ti.align = ti.size + } + return ti, nil +} + +// GetTypeInfo converts a DIE offset into size/align/class/var-count information +// using the high-level *dwarf.Type API (no reader rewinds). +func (d *dwarfReader) GetTypeInfo(off dwarf.Offset) (typeInfo, error) { + if ti, ok := d.typeCache[off]; ok { + return ti, nil + } + t, err := d.Data.Type(off) + if err != nil { + return typeInfo{}, err + } + + ti, err := d.getTypeInfo(t) + d.typeCache[off] = ti + return ti, err +} + +func (d dwarfReader) GoFuncFieldArgs(fn string) (map[string]FuncFieldArg, error) { + log.Printf("Searching for function %s in DWARF data\n", fn) + abi, err := d.DetectSourceABI() + if err != nil { + return nil, err + } + d.argTracker = NewArgTracker(abi, d.Reader.AddressSize()) + // Reset the reader to the start of the DWARF data. + d.Reader.Seek(0) + if !d.GoToEntry(dwarf.TagSubprogram, fn) { + return nil, fmt.Errorf("function %q not found", fn) + } + + funcFields := make(map[string]FuncFieldArg) + argNames := []string{} + var entry *dwarf.Entry + entry, err = d.Reader.Next() + for !errors.Is(err, io.EOF) && entry != nil && + entry.Tag != 0 && entry.Tag == dwarf.TagFormalParameter { + + name := entry.Val(dwarf.AttrName).(string) + + if slices.Contains(argNames, name) { + // Skip this entry as DWARF can generate duplicate entries + log.Printf("Skipping duplicate entry for %s in function %s\n", name, fn) + entry, err = d.Reader.Next() + continue + } + + argNames = append(argNames, name) + typeDie, ok := d.Field(entry, dwarf.AttrType) + if !ok { + return nil, fmt.Errorf("failed to get type attribute for %s: %w", name, ErrDWARFEntry) + } + typeOffset, ok := typeDie.Val.(dwarf.Offset) + if !ok { + return nil, fmt.Errorf("type attribute is not a valid dwarf.Offset for %s: %w", name, ErrDWARFEntry) + } + ti, err := d.GetTypeInfo(typeOffset) + + if err != nil { + return nil, fmt.Errorf("failed to get type info for %s: %w", name, err) + } + + isRetArg := d.IsRetArg(entry) + + funcField, err := d.argTracker.PopLocation(ti.class, ti.size, ti.align, ti.nVars, isRetArg) + if err != nil { + return nil, fmt.Errorf("failed to get location for %s: %w", name, err) + } + funcFields[name] = funcField + entry, err = d.Reader.Next() + } + return funcFields, nil } // GoStructField returns the offset value of a Go struct field. If the struct // field cannot be found -1 and a non-nil error will be returned. -func (d DWARF) GoStructField(id structfield.ID) (int64, error) { +func (d dwarfReader) GoStructField(id structfield.ID) (int64, error) { strct := fmt.Sprintf("%s.%s", id.PkgPath, id.Struct) if !d.GoToEntry(dwarf.TagStructType, strct) { return -1, fmt.Errorf("struct %q not found", strct) @@ -47,14 +444,29 @@ func (d DWARF) GoStructField(id structfield.ID) (int64, error) { // GoToEntry reads until the entry with a tag equal to name is found. True is // returned if the entry is found, otherwise false is returned. -func (d DWARF) GoToEntry(tag dwarf.Tag, name string) bool { +func (d dwarfReader) GoToEntry(tag dwarf.Tag, name string) bool { _, err := d.Entry(tag, name) return err == nil } +func (d dwarfReader) EntriesWithTag(tag dwarf.Tag) ([]*dwarf.Entry, error) { + entries := make([]*dwarf.Entry, 0) + for { + entry, err := d.Reader.Next() + if errors.Is(err, io.EOF) || entry == nil { + break + } + + if entry.Tag == tag { + entries = append(entries, entry) + } + } + return entries, nil +} + // Entry returns the entry with a tag equal to name. ErrDWARFEntry is returned // if the entry cannot be found. -func (d DWARF) Entry(tag dwarf.Tag, name string) (*dwarf.Entry, error) { +func (d dwarfReader) Entry(tag dwarf.Tag, name string) (*dwarf.Entry, error) { for { entry, err := d.Reader.Next() if errors.Is(err, io.EOF) || entry == nil { @@ -75,7 +487,7 @@ func (d DWARF) Entry(tag dwarf.Tag, name string) (*dwarf.Entry, error) { // EntryInChildren returns the entry with a tag equal to name within the // children of the current entry. ErrDWARFEntry is returned if the entry cannot // be found. -func (d DWARF) EntryInChildren(tag dwarf.Tag, name string) (*dwarf.Entry, error) { +func (d dwarfReader) EntryInChildren(tag dwarf.Tag, name string) (*dwarf.Entry, error) { for { entry, err := d.Reader.Next() if errors.Is(err, io.EOF) || entry == nil || entry.Tag == 0 { @@ -95,7 +507,7 @@ func (d DWARF) EntryInChildren(tag dwarf.Tag, name string) (*dwarf.Entry, error) // Field returns the field from the entry e that has attribute a and true. // If no field is found, an empty field is returned with false. -func (d DWARF) Field(e *dwarf.Entry, a dwarf.Attr) (dwarf.Field, bool) { +func (d dwarfReader) Field(e *dwarf.Entry, a dwarf.Attr) (dwarf.Field, bool) { for _, f := range e.Field { if f.Attr == a { return f, true diff --git a/internal/pkg/process/dwarf_test.go b/internal/pkg/process/dwarf_test.go new file mode 100644 index 0000000000..7bea255dc5 --- /dev/null +++ b/internal/pkg/process/dwarf_test.go @@ -0,0 +1,146 @@ +package process + +import ( + "bytes" + "debug/elf" + "encoding/json" + "errors" + "os/exec" + "testing" +) + +func TestGoFuncFieldArgs(t *testing.T) { + tt := []struct { + filename string + funcName string + expectedErr error + }{ + // stdlib tests + { + filename: "testdata/stdlib/app1.23.8", + funcName: "crypto/tls.(*Conn).Write", + expectedErr: nil, + }, + { + filename: "testdata/stdlib/app1.23.8", + funcName: "crypto/tls.(*Conn).Read", + expectedErr: nil, + }, + { + filename: "testdata/stdlib/app1.23.8", + funcName: "net/http.(*http2Framer).WriteDataPadded", + expectedErr: nil, + }, + { + filename: "testdata/stdlib/app1.23.8", + funcName: "net/http.(*http2Framer).checkFrameOrder", + expectedErr: nil, + }, + { + filename: "testdata/stdlib/app1.23.8", + funcName: "net/http.(*http2writeResHeaders).writeFrame", + expectedErr: nil, + }, + { + filename: "testdata/stdlib/app1.23.8", + funcName: "net/http.(*http2serverConn).processHeaders", + expectedErr: nil, + }, + // grpc tests + { + filename: "testdata/grpc/appv1.53.0", + funcName: "google.golang.org/grpc/internal/transport.(*http2Server).operateHeaders", + expectedErr: nil, + }, + { + filename: "testdata/grpc/appv1.53.0", + funcName: "google.golang.org/grpc/internal/transport.(*http2Client).operateHeaders", + expectedErr: nil, + }, + { + filename: "testdata/grpc/appv1.53.0", + funcName: "google.golang.org/grpc/internal/transport.(*loopyWriter).writeHeader", + expectedErr: nil, + }, + { + filename: "testdata/golang-x-net/appv0.37.0", + funcName: "golang.org/x/net/http2.(*Framer).WriteDataPadded", + expectedErr: nil, + }, + { + filename: "testdata/golang-x-net/appv0.37.0", + funcName: "golang.org/x/net/http2.(*Framer).checkFrameOrder", + expectedErr: nil, + }, + { + filename: "testdata/golang-x-net/appv0.37.0", + funcName: "golang.org/x/net/http2/hpack.(*Encoder).WriteField", + expectedErr: nil, + }, + } + + for _, tc := range tt { + t.Run(tc.filename+"_"+tc.funcName, func(t *testing.T) { + elfF, err := elf.Open(tc.filename) + if err != nil { + t.Fatalf("failed to open ELF file %s: %v", tc.filename, err) + } + defer elfF.Close() + dwData, err := elfF.DWARF() + if err != nil { + t.Fatalf("failed to get DWARF data from %s: %v", tc.filename, err) + } + dw := NewDWARF(dwData) + + args, err := dw.GoFuncFieldArgs(tc.funcName) + if !errors.Is(err, tc.expectedErr) { + t.Fatalf("expected error %v, got %v", tc.expectedErr, err) + } + expectedFuncArgs, err := GetFuncArgsFromPx(tc.filename, tc.funcName) + if err != nil { + t.Fatalf("failed to get function args from px: %v", err) + } + if len(expectedFuncArgs) != len(args) { + t.Fatalf("expected %d args from px, got %d", len(expectedFuncArgs), len(args)) + } + + for argName, funcField := range args { + expectedArg, exists := expectedFuncArgs[argName] + if !exists { + t.Errorf("expected arg %s not found in px output", argName) + } else { + // TODO(ddelnano): Fix the violations later + funcField.RetArg = expectedArg.RetArg + if expectedArg != funcField { + t.Errorf("expected arg '%s' %+v to match px output %+v", argName, expectedArg, funcField) + } + } + } + }) + } +} + +// This command runs Pixie's //src/stirling/binaries:go_func_dwarf_dump tool. This ensures that +// the offsetgen matches the output of the Pixie tool, which is used in production +func GetFuncArgsFromPx(filename, funcName string) (map[string]FuncFieldArg, error) { + + // Run exePath with binary and func_names args + // Parse output to get offset and location + // Return offset and location + cmd := exec.Command("testdata/go_func_dwarf_dump", "--binary", filename, "--func_names", funcName) + + var stdout bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + var result map[string]FuncFieldArg + var err error + if err = cmd.Run(); err != nil { + return result, err + } + + err = json.Unmarshal(stdout.Bytes(), &result) + return result, err + +} diff --git a/internal/pkg/process/testdata/app1.24.3 b/internal/pkg/process/testdata/app1.24.3 new file mode 100755 index 0000000000..74cf25f115 Binary files /dev/null and b/internal/pkg/process/testdata/app1.24.3 differ diff --git a/internal/pkg/process/testdata/client b/internal/pkg/process/testdata/client new file mode 100755 index 0000000000..a44db65b66 Binary files /dev/null and b/internal/pkg/process/testdata/client differ diff --git a/internal/pkg/process/testdata/golang-x-net/appv0.37.0 b/internal/pkg/process/testdata/golang-x-net/appv0.37.0 new file mode 100755 index 0000000000..9999ec60f5 Binary files /dev/null and b/internal/pkg/process/testdata/golang-x-net/appv0.37.0 differ diff --git a/internal/pkg/process/testdata/grpc/appv1.53.0 b/internal/pkg/process/testdata/grpc/appv1.53.0 new file mode 100755 index 0000000000..8906ad72e1 Binary files /dev/null and b/internal/pkg/process/testdata/grpc/appv1.53.0 differ diff --git a/internal/pkg/process/testdata/stdlib/app1.23.8 b/internal/pkg/process/testdata/stdlib/app1.23.8 new file mode 100755 index 0000000000..ab54258a8b Binary files /dev/null and b/internal/pkg/process/testdata/stdlib/app1.23.8 differ diff --git a/internal/pkg/structfield/json.go b/internal/pkg/structfield/json.go index daf2d0c3be..3bde2cbe26 100644 --- a/internal/pkg/structfield/json.go +++ b/internal/pkg/structfield/json.go @@ -3,7 +3,10 @@ package structfield -import "github.com/Masterminds/semver/v3" +import ( + "github.com/Masterminds/semver/v3" + "go.opentelemetry.io/auto/internal/pkg/funcfield" +) type jsonOffset struct { Offset *uint64 `json:"offset"` @@ -37,6 +40,54 @@ func (jf *jsonField) addOffsets(off *Offsets) { } } +type jsonFuncOffset struct { + Offset *uint64 `json:"offset"` + Location funcfield.Location `json:"location"` + Versions []*semver.Version `json:"versions"` +} + +type jsonFuncArg struct { + Arg string `json:"arg"` + Offsets []*jsonFuncOffset `json:"offsets"` +} + +func (jf *jsonFuncArg) addOffsets(off *funcfield.Offsets) { + var jOff *jsonFuncOffset + for o, vers := range off.Index() { + if !o.Valid { + jOff = find(&jf.Offsets, func(jo *jsonFuncOffset) bool { + return jo.Offset == nil + }) + jOff.Offset = nil + jOff.Location = funcfield.Unknown + } else { + jOff = find(&jf.Offsets, func(jo *jsonFuncOffset) bool { + return jo.Offset != nil && o.Offset == *jo.Offset + }) + offTmp := o + jOff.Offset = &offTmp.Offset + jOff.Location = offTmp.Location + } + + jOff.Versions = mergeSorted(jOff.Versions, vers, func(a, b *semver.Version) int { + return a.Compare(b) + }) + } +} + +type jsonFunc struct { + Func string `json:"func"` + Args []*jsonFuncArg `json:"args"` +} + +func (jf *jsonFunc) addOffsets(arg string, off *funcfield.Offsets) { + jfa := find(&jf.Args, func(jfa *jsonFuncArg) bool { + return arg == jfa.Arg + }) + jfa.Arg = arg + jfa.addOffsets(off) +} + type jsonStruct struct { Struct string `json:"struct"` Fields []*jsonField `json:"fields"` @@ -53,6 +104,7 @@ func (js *jsonStruct) addOffsets(field string, off *Offsets) { type jsonPackage struct { Package string `json:"package"` Structs []*jsonStruct `json:"structs"` + Funcs []*jsonFunc `json:"funcs"` } func (jp *jsonPackage) addOffsets(strct, field string, off *Offsets) { @@ -63,6 +115,14 @@ func (jp *jsonPackage) addOffsets(strct, field string, off *Offsets) { js.addOffsets(field, off) } +func (jp *jsonPackage) addFuncOffsets(fn, arg string, off *funcfield.Offsets) { + jf := find(&jp.Funcs, func(s *jsonFunc) bool { + return fn == s.Func + }) + jf.Func = fn + jf.addOffsets(arg, off) +} + type jsonModule struct { Module string `json:"module"` Packages []*jsonPackage `json:"packages"` @@ -76,6 +136,14 @@ func (jm *jsonModule) addOffsets(pkg, strct, field string, off *Offsets) { jp.addOffsets(strct, field, off) } +func (jm *jsonModule) addFuncOffsets(pkg, fn, arg string, off *funcfield.Offsets) { + jp := find(&jm.Packages, func(p *jsonPackage) bool { + return pkg == p.Package + }) + jp.Package = pkg + jp.addFuncOffsets(fn, arg, off) +} + // find returns the value in slice where f evaluates to true. If none exists a // new value of *T is created and appended to slice. func find[T any](slice *[]*T, f func(*T) bool) *T { diff --git a/internal/pkg/structfield/structfield.go b/internal/pkg/structfield/structfield.go index b6ad2815b2..ad2bd0b78a 100644 --- a/internal/pkg/structfield/structfield.go +++ b/internal/pkg/structfield/structfield.go @@ -12,17 +12,20 @@ import ( "sync" "github.com/Masterminds/semver/v3" + "go.opentelemetry.io/auto/internal/pkg/funcfield" ) // Index holds all struct field offsets. type Index struct { - dataMu sync.RWMutex - data map[ID]*Offsets + dataMu sync.RWMutex + data map[ID]*Offsets + funcsMu sync.RWMutex + funcs map[funcfield.ID]*funcfield.Offsets } // NewIndex returns a new empty Index. func NewIndex() *Index { - return &Index{data: make(map[ID]*Offsets)} + return &Index{data: make(map[ID]*Offsets), funcs: make(map[funcfield.ID]*funcfield.Offsets)} } // Get returns the Offsets and true for an id contained in the Index i. It will @@ -34,11 +37,23 @@ func (i *Index) Get(id ID) (*Offsets, bool) { return i.get(id) } +func (i *Index) GetFunc(id funcfield.ID, ver *semver.Version) (funcfield.OffsetKey, bool) { + i.funcsMu.RLock() + defer i.funcsMu.RUnlock() + + return i.getfuncOffset(id, ver) +} + func (i *Index) get(id ID) (*Offsets, bool) { o, ok := i.data[id] return o, ok } +func (i *Index) getfunc(id funcfield.ID) (*funcfield.Offsets, bool) { + o, ok := i.funcs[id] + return o, ok +} + // GetOffset returns the offset value and true for the version ver of id // contained in the Index i. It will return zero and false for any id not // contained in i. @@ -63,6 +78,26 @@ func (i *Index) GetLatestOffset(id ID) (OffsetKey, *semver.Version) { return off, &ver.Version } +func (i *Index) GetLatestFuncOffset(id funcfield.ID) (funcfield.OffsetKey, *semver.Version) { + i.funcsMu.RLock() + defer i.funcsMu.RUnlock() + + offs, ok := i.getfunc(id) + if !ok { + return funcfield.OffsetKey{}, nil + } + off, ver := offs.GetLatest() + return off, &ver.Version +} + +func (i *Index) getfuncOffset(id funcfield.ID, ver *semver.Version) (funcfield.OffsetKey, bool) { + offs, ok := i.getfunc(id) + if !ok { + return funcfield.OffsetKey{}, false + } + return offs.Get(ver) +} + func (i *Index) getOffset(id ID, ver *semver.Version) (OffsetKey, bool) { offs, ok := i.get(id) if !ok { @@ -87,6 +122,10 @@ func (i *Index) put(id ID, offsets *Offsets) { i.data[id] = offsets } +func (i *Index) putfunc(id funcfield.ID, offsets *funcfield.Offsets) { + i.funcs[id] = offsets +} + // PutOffset stores the offset value for version ver of id within the Index i. // // This will update any existing offsets stored for id with offset. If ver @@ -107,6 +146,22 @@ func (i *Index) putOffset(id ID, ver *semver.Version, offset uint64, valid bool) off.Put(ver, OffsetKey{Offset: offset, Valid: valid}) } +func (i *Index) PutFuncOffset(id funcfield.ID, ver *semver.Version, offset uint64, location funcfield.Location, valid bool) { + i.dataMu.Lock() + defer i.dataMu.Unlock() + + i.putFuncOffset(id, ver, offset, location, valid) +} + +func (i *Index) putFuncOffset(id funcfield.ID, ver *semver.Version, offset uint64, location funcfield.Location, valid bool) { + off, ok := i.getfunc(id) + if !ok { + off = funcfield.NewOffsets() + i.putfunc(id, off) + } + off.Put(ver, funcfield.OffsetKey{Offset: offset, Location: location, Valid: valid}) +} + // UnmarshalJSON unmarshals the offset JSON data into i. func (i *Index) UnmarshalJSON(data []byte) error { var mods []*jsonModule @@ -116,6 +171,7 @@ func (i *Index) UnmarshalJSON(data []byte) error { } m := make(map[ID]*Offsets) + fnMap := make(map[funcfield.ID]*funcfield.Offsets) for _, mod := range mods { for _, p := range mod.Packages { @@ -145,6 +201,33 @@ func (i *Index) UnmarshalJSON(data []byte) error { } } } + + for _, f := range p.Funcs { + for _, arg := range f.Args { + for _, o := range arg.Offsets { + for _, v := range o.Versions { + key := funcfield.ID{ + ModPath: mod.Module, + PkgPath: p.Package, + Func: f.Func, + Arg: arg.Arg, + } + + off, ok := fnMap[key] + if !ok { + off = new(funcfield.Offsets) + fnMap[key] = off + } + + if o.Offset == nil { + off.Put(v, funcfield.OffsetKey{Valid: false}) + } else { + off.Put(v, funcfield.OffsetKey{Offset: *o.Offset, Location: o.Location, Valid: true}) + } + } + } + } + } } } @@ -152,6 +235,10 @@ func (i *Index) UnmarshalJSON(data []byte) error { i.data = m i.dataMu.Unlock() + i.funcsMu.Lock() + i.funcs = fnMap + i.funcsMu.Unlock() + return nil } @@ -169,6 +256,14 @@ func (i *Index) MarshalJSON() ([]byte, error) { jm.addOffsets(id.PkgPath, id.Struct, id.Field, off) } + for id, off := range i.funcs { + jm := find(&out, func(p *jsonModule) bool { + return id.ModPath == p.Module + }) + jm.Module = id.ModPath + jm.addFuncOffsets(id.PkgPath, id.Func, id.Arg, off) + } + // Ensure repeatability by sorting. for _, m := range out { for _, p := range m.Packages { @@ -191,6 +286,28 @@ func (i *Index) MarshalJSON() ([]byte, error) { sort.Slice(p.Structs, func(i, j int) bool { return p.Structs[i].Struct < p.Structs[j].Struct }) + + for _, f := range p.Funcs { + for _, arg := range f.Args { + // TODO(ddelnano): Args should ideally be sorted by the dwarf.TagFormalParameter + // position from within the dwarf.TagSubroutineType + sort.Slice(arg.Offsets, func(i, j int) bool { + if arg.Offsets[i].Offset == nil { + return true + } + if arg.Offsets[j].Offset == nil { + return false + } + return *arg.Offsets[i].Offset < *arg.Offsets[j].Offset + }) + } + sort.Slice(f.Args, func(i, j int) bool { + return f.Args[i].Arg < f.Args[j].Arg + }) + } + sort.Slice(p.Funcs, func(i, j int) bool { + return p.Funcs[i].Func < p.Funcs[j].Func + }) } sort.Slice(m.Packages, func(i, j int) bool { return m.Packages[i].Package < m.Packages[j].Package @@ -199,7 +316,6 @@ func (i *Index) MarshalJSON() ([]byte, error) { sort.Slice(out, func(i, j int) bool { return out[i].Module < out[j].Module }) - return json.Marshal(out) } diff --git a/internal/pkg/structfield/structfield_test.go b/internal/pkg/structfield/structfield_test.go index f6bc2bec3a..ef653a0078 100644 --- a/internal/pkg/structfield/structfield_test.go +++ b/internal/pkg/structfield/structfield_test.go @@ -13,6 +13,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/auto/internal/pkg/funcfield" ) var ( @@ -68,6 +69,51 @@ func TestOffsets(t *testing.T) { assert.Equal(t, OffsetKey{Offset: 2, Valid: true}, off, "invalid update value for 1.2.0") } +func TestFuncOffsets(t *testing.T) { + var o funcfield.Offsets + + off, ok := o.Get(v120) + assert.False(t, ok, "empty offsets found value") + assert.Equal(t, funcfield.OffsetKey{Offset: 0, Valid: false}, off, "empty offset value") + + o.Put(v120, funcfield.OffsetKey{Offset: 1, Valid: true}) + o.Put(v121, funcfield.OffsetKey{Offset: 2, Valid: true}) + o.Put(v130, funcfield.OffsetKey{Offset: 0, Valid: false}) + + off, ok = o.Get(v120) + assert.True(t, ok, "did not get 1.2.0") + assert.Equal(t, funcfield.OffsetKey{Offset: 1, Valid: true}, off, "invalid value for 1.2.0") + + off, ok = o.Get(v12) + assert.True(t, ok, "did not get 1.2") + assert.Equal(t, funcfield.OffsetKey{Offset: 1, Valid: true}, off, "invalid value for 1.2") + + off, ok = o.Get(v130) + assert.True(t, ok, "did not get 1.3.0") + assert.Equal(t, funcfield.OffsetKey{Offset: 0, Valid: false}, off, "invalid value for 1.3.0") + + _, ok = o.Get(v110) + assert.False(t, ok, "found value for 1.1.0") + + off, ok = o.Get(v121) + assert.True(t, ok, "did not get 1.2.1") + assert.Equal(t, funcfield.OffsetKey{Offset: 2, Valid: true}, off, "invalid value for 1.2.1") + + off, ver := o.GetLatest() + assert.Equal(t, v121, &ver.Version, "invalid version for latest") + assert.Equal(t, funcfield.OffsetKey{Offset: 2, Valid: true}, off, "invalid value for latest") + + o.Put(v120, funcfield.OffsetKey{Offset: 1, Valid: true}) + off, ok = o.Get(v120) + assert.True(t, ok, "did not get 1.2.0 after reset") + assert.Equal(t, funcfield.OffsetKey{Offset: 1, Valid: true}, off, "invalid reset value for 1.2.0") + + o.Put(v120, funcfield.OffsetKey{Offset: 2, Valid: true}) + off, ok = o.Get(v120) + assert.True(t, ok, "did not get 1.2.0 after update") + assert.Equal(t, funcfield.OffsetKey{Offset: 2, Valid: true}, off, "invalid update value for 1.2.0") +} + var index = &Index{ data: map[ID]*Offsets{ NewID("std", "net/http", "Request", "Method"): { @@ -101,6 +147,40 @@ var index = &Index{ uo: uniqueOffset{value: 0, valid: true}, }, }, + funcs: map[funcfield.ID]*funcfield.Offsets{ + funcfield.NewID("std", "crypto/tls", "(*Conn).Read", "c"): { + Ua: funcfield.UniqueOffset{Value: 0, Location: funcfield.Registers, Valid: true}, + Values: map[funcfield.VerKey]funcfield.OffsetVersion{ + funcfield.NewVerKey(v120): {Offset: funcfield.OffsetKey{Offset: 0, Location: funcfield.Registers, Valid: true}, Version: v120}, + funcfield.NewVerKey(v121): {Offset: funcfield.OffsetKey{Offset: 0, Location: funcfield.Registers, Valid: true}, Version: v121}, + funcfield.NewVerKey(v130): {Offset: funcfield.OffsetKey{Offset: 0, Location: funcfield.Registers, Valid: true}, Version: v130}, + }, + }, + funcfield.NewID("std", "crypto/tls", "(*Conn).Read", "b"): { + Ua: funcfield.UniqueOffset{Value: 8, Location: funcfield.Registers, Valid: true}, + Values: map[funcfield.VerKey]funcfield.OffsetVersion{ + funcfield.NewVerKey(v120): {Offset: funcfield.OffsetKey{Offset: 8, Location: funcfield.Registers, Valid: true}, Version: v120}, + funcfield.NewVerKey(v121): {Offset: funcfield.OffsetKey{Offset: 8, Location: funcfield.Registers, Valid: true}, Version: v121}, + funcfield.NewVerKey(v130): {Offset: funcfield.OffsetKey{Offset: 8, Location: funcfield.Registers, Valid: true}, Version: v130}, + }, + }, + funcfield.NewID("std", "crypto/tls", "(*Conn).Read", "~r0"): { + Ua: funcfield.UniqueOffset{Value: 0, Location: funcfield.Registers, Valid: true}, + Values: map[funcfield.VerKey]funcfield.OffsetVersion{ + funcfield.NewVerKey(v120): {Offset: funcfield.OffsetKey{Offset: 0, Location: funcfield.Registers, Valid: true}, Version: v120}, + funcfield.NewVerKey(v121): {Offset: funcfield.OffsetKey{Offset: 0, Location: funcfield.Registers, Valid: true}, Version: v121}, + funcfield.NewVerKey(v130): {Offset: funcfield.OffsetKey{Offset: 0, Location: funcfield.Registers, Valid: true}, Version: v130}, + }, + }, + funcfield.NewID("std", "crypto/tls", "(*Conn).Read", "~r1"): { + Ua: funcfield.UniqueOffset{Value: 8, Location: funcfield.Registers, Valid: true}, + Values: map[funcfield.VerKey]funcfield.OffsetVersion{ + funcfield.NewVerKey(v120): {Offset: funcfield.OffsetKey{Offset: 8, Location: funcfield.Registers, Valid: true}, Version: v120}, + funcfield.NewVerKey(v121): {Offset: funcfield.OffsetKey{Offset: 8, Location: funcfield.Registers, Valid: true}, Version: v121}, + funcfield.NewVerKey(v130): {Offset: funcfield.OffsetKey{Offset: 8, Location: funcfield.Registers, Valid: true}, Version: v130}, + }, + }, + }, } func TestIndexMarshalJSON(t *testing.T) { @@ -146,4 +226,20 @@ func TestGetLatestOffsetFromIndex(t *testing.T) { ) assert.Equal(t, v120, ver, "invalid version for ClientConn.target") assert.Equal(t, OffsetKey{Offset: 0, Valid: true}, off, "invalid value for ClientConn.target") + + funcOff, ver := index.GetLatestFuncOffset(funcfield.NewID("std", "crypto/tls", "(*Conn).Read", "c")) + assert.Equal(t, v130, ver, "invalid version for crypto/tls.(*Conn).Read.c") + assert.Equal(t, funcfield.OffsetKey{Offset: 0, Location: funcfield.Registers, Valid: true}, funcOff, "invalid value for crypto/tls.(*Conn).Read.c") + + funcOff, ver = index.GetLatestFuncOffset(funcfield.NewID("std", "crypto/tls", "(*Conn).Read", "b")) + assert.Equal(t, v130, ver, "invalid version for crypto/tls.(*Conn).Read.b") + assert.Equal(t, funcfield.OffsetKey{Offset: 8, Location: funcfield.Registers, Valid: true}, funcOff, "invalid value for crypto/tls.(*Conn).Read.b") + + funcOff, ver = index.GetLatestFuncOffset(funcfield.NewID("std", "crypto/tls", "(*Conn).Read", "~r0")) + assert.Equal(t, v130, ver, "invalid version for crypto/tls.(*Conn).Read.~r0") + assert.Equal(t, funcfield.OffsetKey{Offset: 0, Location: funcfield.Registers, Valid: true}, funcOff, "invalid value for crypto/tls.(*Conn).Read.~r0") + + funcOff, ver = index.GetLatestFuncOffset(funcfield.NewID("std", "crypto/tls", "(*Conn).Read", "~r1")) + assert.Equal(t, v130, ver, "invalid version for crypto/tls.(*Conn).Read.~r1") + assert.Equal(t, funcfield.OffsetKey{Offset: 8, Location: funcfield.Registers, Valid: true}, funcOff, "invalid value for crypto/tls.(*Conn).Read.~r1") } diff --git a/internal/pkg/structfield/testdata/offsets.json b/internal/pkg/structfield/testdata/offsets.json index 7f7f5e0528..3987dd05f9 100644 --- a/internal/pkg/structfield/testdata/offsets.json +++ b/internal/pkg/structfield/testdata/offsets.json @@ -21,13 +21,82 @@ } ] } - ] + ], + "funcs": null } ] }, { "module": "std", "packages": [ + { + "package": "crypto/tls", + "structs": null, + "funcs": [ + { + "func": "(*Conn).Read", + "args": [ + { + "arg": "b", + "offsets": [ + { + "offset": 8, + "location": "registers", + "versions": [ + "1.2.0", + "1.2.1", + "1.3.0" + ] + } + ] + }, + { + "arg": "c", + "offsets": [ + { + "offset": 0, + "location": "registers", + "versions": [ + "1.2.0", + "1.2.1", + "1.3.0" + ] + } + ] + }, + { + "arg": "~r0", + "offsets": [ + { + "offset": 0, + "location": "registers", + "versions": [ + "1.2.0", + "1.2.1", + "1.3.0" + ] + } + ] + }, + { + "arg": "~r1", + "offsets": [ + { + "offset": 8, + "location": "registers", + "versions": [ + "1.2.0", + "1.2.1", + "1.3.0" + ] + } + ] + } + ] + } + + ] + }, { "package": "net/http", "structs": [ @@ -100,7 +169,8 @@ } ] } - ] + ], + "funcs": null } ] } diff --git a/internal/test/e2e/go.mod b/internal/test/e2e/go.mod index e0300b0a68..dd107267f9 100644 --- a/internal/test/e2e/go.mod +++ b/internal/test/e2e/go.mod @@ -4,7 +4,7 @@ go 1.23.0 require ( github.com/cilium/ebpf v0.18.0 - github.com/docker/docker v28.1.1+incompatible + github.com/docker/docker v28.2.2+incompatible github.com/docker/go-connections v0.5.0 github.com/gin-gonic/gin v1.10.1 github.com/mattn/go-sqlite3 v1.14.28 @@ -17,7 +17,7 @@ require ( go.opentelemetry.io/otel/trace v1.36.0 go.uber.org/goleak v1.3.0 google.golang.org/grpc v1.72.2 - google.golang.org/grpc/examples v0.0.0-20250526155028-4cab0e6dc6e7 + google.golang.org/grpc/examples v0.0.0-20250529183914-4275c5bdd8e8 ) require ( @@ -29,6 +29,8 @@ require ( github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.5 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect @@ -36,7 +38,7 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.4.9 // indirect github.com/gin-contrib/sse v1.1.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -89,15 +91,15 @@ require ( go.opentelemetry.io/otel/sdk v1.36.0 // indirect go.opentelemetry.io/otel/sdk/log v0.12.2 // indirect go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect - go.opentelemetry.io/proto/otlp v1.6.0 // indirect + go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.17.0 // indirect golang.org/x/crypto v0.38.0 // indirect golang.org/x/net v0.40.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/text v0.25.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.2 // indirect diff --git a/internal/test/e2e/go.sum b/internal/test/e2e/go.sum index b1a0c1fcaf..64af6d50aa 100644 --- a/internal/test/e2e/go.sum +++ b/internal/test/e2e/go.sum @@ -20,6 +20,10 @@ github.com/cilium/ebpf v0.18.0/go.mod h1:vmsAT73y4lW2b4peE+qcOqw6MxvWQdC+LiU5gd/ github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -27,8 +31,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I= -github.com/docker/docker v28.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.2.2+incompatible h1:CjwRSksz8Yo4+RmQ339Dp/D2tGO5JxwYeqtMOEe0LDw= +github.com/docker/docker v28.2.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -42,8 +46,8 @@ github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fq github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -215,8 +219,8 @@ go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFw go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= -go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= -go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= +go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= +go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -291,14 +295,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= -google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= -google.golang.org/grpc/examples v0.0.0-20250526155028-4cab0e6dc6e7 h1:qmTRTvUbC4g5DBQbWBBaK8fZfUH0nV7F0Vr0MfLr2Lw= -google.golang.org/grpc/examples v0.0.0-20250526155028-4cab0e6dc6e7/go.mod h1:tVWJxR8lMn4AFXavKgoU/QtZvQ+E6K1HNS6Q/FuqMxc= +google.golang.org/grpc/examples v0.0.0-20250529183914-4275c5bdd8e8 h1:Bg6BAkcMOv5OTrtwrsbn8ACXyCdoabDA7jcfekA/T24= +google.golang.org/grpc/examples v0.0.0-20250529183914-4275c5bdd8e8/go.mod h1:tVWJxR8lMn4AFXavKgoU/QtZvQ+E6K1HNS6Q/FuqMxc= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/test/e2e/kafka-go/cmd/dependencies.Dockerfile b/internal/test/e2e/kafka-go/cmd/dependencies.Dockerfile index 6bbf85b911..3fd331ba29 100644 --- a/internal/test/e2e/kafka-go/cmd/dependencies.Dockerfile +++ b/internal/test/e2e/kafka-go/cmd/dependencies.Dockerfile @@ -1 +1 @@ -FROM bitnami/kafka:latest@sha256:8a85b48e25ecd9a59db363b2ff89219e1c24cd5cf073bb66853c3b26c3bfa149 AS kafka +FROM bitnami/kafka:latest@sha256:6cd4f5e8822e5b649f37bbfca86649e6832b320430e9dd5cd1367b0974f4911d AS kafka diff --git a/internal/tools/go.mod b/internal/tools/go.mod index b5f88d3d7c..0f311b0746 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -4,7 +4,7 @@ go 1.23.0 require ( github.com/Masterminds/semver/v3 v3.3.1 - github.com/docker/docker v28.1.1+incompatible + github.com/docker/docker v28.2.2+incompatible github.com/golangci/golangci-lint/v2 v2.1.6 github.com/google/go-licenses/v2 v2.0.0-alpha.1 go.opentelemetry.io/auto v0.22.0 @@ -19,7 +19,7 @@ require ( 4d63.com/gochecknoglobals v0.2.2 // indirect dario.cat/mergo v1.0.2 // indirect github.com/4meepo/tagalign v1.4.2 // indirect - github.com/Abirdcfly/dupword v0.1.4 // indirect + github.com/Abirdcfly/dupword v0.1.6 // indirect github.com/Antonboom/errname v1.1.0 // indirect github.com/Antonboom/nilnil v1.1.0 // indirect github.com/Antonboom/testifylint v1.6.1 // indirect @@ -59,6 +59,8 @@ require ( github.com/cilium/ebpf v0.18.0 // indirect github.com/ckaznocha/intrange v0.3.1 // indirect github.com/cloudflare/circl v1.6.1 // indirect + github.com/containerd/errdefs v1.0.0 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/curioswitch/go-reassign v0.3.0 // indirect github.com/cyphar/filepath-securejoin v0.4.1 // indirect @@ -83,7 +85,7 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/go-git/go-git/v5 v5.16.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect @@ -238,15 +240,15 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.17.0 // indirect golang.org/x/crypto v0.38.0 // indirect - golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect - golang.org/x/exp/typeparams v0.0.0-20250506013437-ce4c2cf36ca6 // indirect + golang.org/x/exp v0.0.0-20250530174510-65e920069ea6 // indirect + golang.org/x/exp/typeparams v0.0.0-20250530174510-65e920069ea6 // indirect golang.org/x/mod v0.24.0 // indirect golang.org/x/net v0.40.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/text v0.25.0 // indirect golang.org/x/tools v0.33.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/grpc v1.72.2 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/internal/tools/go.sum b/internal/tools/go.sum index 805c0ed4f2..c9741844b0 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -7,8 +7,8 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.4 h1:jxqkdgO0L7FSwq4fMu3d+fAA1E3bBQAtl4utA3tcQZM= -github.com/Abirdcfly/dupword v0.1.4/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= +github.com/Abirdcfly/dupword v0.1.6 h1:qeL6u0442RPRe3mcaLcbaCi2/Y/hOcdtw6DE9odjz9c= +github.com/Abirdcfly/dupword v0.1.6/go.mod h1:s+BFMuL/I4YSiFv29snqyjwzDp4b65W2Kvy+PKzZ6cw= github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= @@ -106,6 +106,10 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -129,8 +133,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I= -github.com/docker/docker v28.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.2.2+incompatible h1:CjwRSksz8Yo4+RmQ339Dp/D2tGO5JxwYeqtMOEe0LDw= +github.com/docker/docker v28.2.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -174,8 +178,8 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod github.com/go-git/go-git/v5 v5.16.0 h1:k3kuOEpkc0DeY7xlL6NaaNg39xdgQbtH5mwCafHO9AQ= github.com/go-git/go-git/v5 v5.16.0/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6 h1:teYtXy9B7y5lHTp8V9KPxpYRAVA7dozigQcMiBust1s= @@ -602,8 +606,8 @@ go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFw go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= -go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= -go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= +go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= +go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -624,12 +628,12 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI= -golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= +golang.org/x/exp v0.0.0-20250530174510-65e920069ea6 h1:gllJVKwONftmCc4KlNbN8o/LvmbxotqQy6zzi6yDQOQ= +golang.org/x/exp v0.0.0-20250530174510-65e920069ea6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20250506013437-ce4c2cf36ca6 h1:UW7ILaA/QTIxnBKbgCV+72w0gRw97+MY93VyPjnGZJU= -golang.org/x/exp/typeparams v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:LKZHyeOpPuZcMgxeHjJp4p5yvxrCX1xDvH10zYHhjjQ= +golang.org/x/exp/typeparams v0.0.0-20250530174510-65e920069ea6 h1:Gq937g8bNiCnWB/wsoyxuxnfDpAE9cpYo4sLIp9t0LA= +golang.org/x/exp/typeparams v0.0.0-20250530174510-65e920069ea6/go.mod h1:LKZHyeOpPuZcMgxeHjJp4p5yvxrCX1xDvH10zYHhjjQ= 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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -767,10 +771,10 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0= -google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a h1:SGktgSolFCo75dnHJF2yMvnns6jCmHFJ0vE4Vn2JKvQ= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/internal/tools/inspect/app.go b/internal/tools/inspect/app.go index e4874e650b..963c0e3732 100644 --- a/internal/tools/inspect/app.go +++ b/internal/tools/inspect/app.go @@ -10,11 +10,14 @@ import ( "debug/dwarf" "debug/elf" "errors" + "fmt" + "log" "log/slog" "os" "github.com/Masterminds/semver/v3" + "go.opentelemetry.io/auto/internal/pkg/funcfield" "go.opentelemetry.io/auto/internal/pkg/process" "go.opentelemetry.io/auto/internal/pkg/structfield" ) @@ -59,10 +62,16 @@ func newApp(ctx context.Context, l *slog.Logger, j job) (*app, error) { return nil, err } - if len(j.Fields) == 0 { + if len(j.Fields) == 0 && len(j.Funcs) == 0 { return nil, errors.New("no fields to analyze") } - modName := j.Fields[0].ModPath + var modName string + if len(j.Fields) > 0 { + + modName = j.Fields[0].ModPath + } else { + modName = j.Funcs[0].ModPath + } a.exec, err = j.Builder.Build(ctx, a.tmpDir, a.AppVer, modName) if err != nil { @@ -84,12 +93,12 @@ func newApp(ctx context.Context, l *slog.Logger, j job) (*app, error) { return a, nil } -// GetOffset returnst the struct field offset for sf. It uses the DWARF data +// GetOffset returns the struct field offset for sf. It uses the DWARF data // of the app's built binary to find this value. func (a *app) GetOffset(id structfield.ID) (uint64, bool) { a.log.Debug("analyzing binary...", "id", id, "binary", a.exec) - d := process.DWARF{Reader: a.data.Reader()} + d := process.NewDWARF(a.data) v, err := d.GoStructField(id) if err != nil || v < 0 { a.log.Error( @@ -104,6 +113,33 @@ func (a *app) GetOffset(id structfield.ID) (uint64, bool) { return uint64(v), true } +func (a *app) GetFuncFieldArgs(fn string) map[string]process.FuncFieldArg { + d := process.NewDWARF(a.data) + result, err := d.GoFuncFieldArgs(fn) + if err != nil { + a.log.Error("failed to get func field args", "error", err, "fn", fn) + return nil + } + + return result +} + +func (a *app) GetFuncArgs(id funcfield.ID) (uint64, funcfield.Location, bool) { + log.Println("analyzing binary...", "id", id, "binary", a.exec) + a.log.Info("analyzing binary...", "id", id, "binary", a.exec) + + // TODO(ddelnano): Add mode where this can be tested against Pixie's dwarf reader dumper binary. + var result map[string]process.FuncFieldArg = a.GetFuncFieldArgs(fmt.Sprintf("%s.%s", id.PkgPath, id.Func)) + arg, ok := result[id.Arg] + + if !ok { + return 0, funcfield.Unknown, false + } + + fmt.Println("Found arg: %v", arg) + return arg.Offset, arg.Location, true +} + // Close closes the app, releasing all held resources. func (a *app) Close() error { return os.RemoveAll(a.tmpDir) diff --git a/internal/tools/inspect/builder.go b/internal/tools/inspect/builder.go index abbbebe4fe..c20d2cfa3e 100644 --- a/internal/tools/inspect/builder.go +++ b/internal/tools/inspect/builder.go @@ -65,7 +65,7 @@ func (b *builder) Build( appV *semver.Version, modName string, ) (string, error) { - b.log.Debug("building application...", "version", appV, "dir", dir, "image", b.GoImage) + b.log.Info("building application...", "version", appV, "dir", dir, "image", b.GoImage) app := "app" + appV.Original() goGetCmd := fmt.Sprintf("go get %s@%s", modName, appV.Original()) @@ -83,15 +83,16 @@ func (b *builder) Build( } if err := b.runCmd(ctx, []string{"sh", "-c", cmd}, dir); err != nil { + fmt.Printf("Build err %v", err) return "", err } - b.log.Debug("built application", "version", appV, "dir", dir, "image", b.GoImage) + b.log.Info("built application", "version", appV, "dir", dir, "image", b.GoImage) return filepath.Join(dir, app), nil } func (b *builder) runCmd(ctx context.Context, cmd []string, dir string) error { - b.log.Debug("running command...", "cmd", cmd, "dir", dir, "image", b.GoImage) + b.log.Info("running command...", "cmd", cmd, "dir", dir, "image", b.GoImage) err := b.pullImage(ctx) if err != nil { diff --git a/internal/tools/inspect/cache.go b/internal/tools/inspect/cache.go index 8a1b9d08d6..dff07bb316 100644 --- a/internal/tools/inspect/cache.go +++ b/internal/tools/inspect/cache.go @@ -10,6 +10,7 @@ import ( "github.com/Masterminds/semver/v3" + "go.opentelemetry.io/auto/internal/pkg/funcfield" "go.opentelemetry.io/auto/internal/pkg/structfield" ) @@ -42,6 +43,22 @@ func newCache(l *slog.Logger) *Cache { // GetOffset returns the cached offset key and true for the id at the specified // version is found in the cache. If the cache does not contain a valid offset for the provided // values, 0 and false are returned. +func (c *Cache) GetFuncOffset(ver *semver.Version, id funcfield.ID) (funcfield.OffsetKey, bool) { + if c.data == nil { + return funcfield.OffsetKey{}, false + } + + off, ok := c.data.GetFunc(id, ver) + msg := "cache " + if ok { + msg += "hit" + } else { + msg += "miss" + } + c.log.Info(msg, "version", ver, "id", id) + return off, ok +} + func (c *Cache) GetOffset(ver *semver.Version, id structfield.ID) (structfield.OffsetKey, bool) { if c.data == nil { return structfield.OffsetKey{}, false diff --git a/internal/tools/inspect/cmd/offsetgen/main.go b/internal/tools/inspect/cmd/offsetgen/main.go index 492b711d69..fe2bb1c7b1 100644 --- a/internal/tools/inspect/cmd/offsetgen/main.go +++ b/internal/tools/inspect/cmd/offsetgen/main.go @@ -15,6 +15,7 @@ import ( "os/signal" "runtime" + "go.opentelemetry.io/auto/internal/pkg/funcfield" "go.opentelemetry.io/auto/internal/pkg/structfield" "go.opentelemetry.io/auto/internal/tools/inspect" ) @@ -65,21 +66,67 @@ func manifests() ([]inspect.Manifest, error) { return nil, fmt.Errorf("failed to get \"golang.org/x/net\" versions: %w", err) } - goOtelVers, err := PkgVersions("go.opentelemetry.io/otel") - if err != nil { - return nil, fmt.Errorf("failed to get \"go.opentelemetry.io/otel\" versions: %w", err) - } - - kafkaGoVers, err := PkgVersions("github.com/segmentio/kafka-go") - if err != nil { - return nil, fmt.Errorf("failed to get \"github.com/segmentio/kafka-go\" versions: %w", err) - } - ren := func(src string) inspect.Renderer { return inspect.NewRenderer(logger, src, inspect.DefaultFS) } return []inspect.Manifest{ + { + Application: inspect.Application{ + Renderer: ren("templates/crypto/tls/*.tmpl"), + GoVerions: goVers, + }, + Funcs: []funcfield.ID{ + funcfield.ID{ + ModPath: "std", + PkgPath: "crypto/tls", + Func: "(*Conn).Read", + Arg: "c", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "crypto/tls", + Func: "(*Conn).Read", + Arg: "b", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "crypto/tls", + Func: "(*Conn).Read", + Arg: "~r0", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "crypto/tls", + Func: "(*Conn).Read", + Arg: "~r1", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "crypto/tls", + Func: "(*Conn).Write", + Arg: "c", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "crypto/tls", + Func: "(*Conn).Write", + Arg: "b", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "crypto/tls", + Func: "(*Conn).Write", + Arg: "~r0", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "crypto/tls", + Func: "(*Conn).Write", + Arg: "~r1", + }, + }, + }, { Application: inspect.Application{ Renderer: ren("templates/runtime/*.tmpl"), @@ -96,36 +143,98 @@ func manifests() ([]inspect.Manifest, error) { GoVerions: goVers, }, StructFields: []structfield.ID{ - structfield.NewID("std", "net/http", "Request", "Method"), - structfield.NewID("std", "net/http", "Request", "URL"), - structfield.NewID("std", "net/http", "Request", "RemoteAddr"), - structfield.NewID("std", "net/http", "Request", "Header"), - structfield.NewID("std", "net/http", "Request", "ctx"), - structfield.NewID("std", "net/http", "Response", "StatusCode"), - structfield.NewID("std", "net/http", "response", "req"), - structfield.NewID("std", "net/http", "response", "status"), - structfield.NewID("std", "net/http", "Request", "Proto"), - structfield.NewID("std", "net/http", "Request", "RequestURI"), - structfield.NewID("std", "net/http", "Request", "Host"), - structfield.NewID("std", "net/http", "Request", "Pattern"), - structfield.NewID("std", "net/http", "Request", "pat"), - structfield.NewID("std", "net/http", "pattern", "str"), - structfield.NewID("std", "net/url", "URL", "Path"), - structfield.NewID("std", "net/url", "URL", "Scheme"), - structfield.NewID("std", "net/url", "URL", "Opaque"), - structfield.NewID("std", "net/url", "URL", "User"), - structfield.NewID("std", "net/url", "URL", "RawPath"), - structfield.NewID("std", "net/url", "URL", "OmitHost"), - structfield.NewID("std", "net/url", "URL", "ForceQuery"), - structfield.NewID("std", "net/url", "URL", "RawQuery"), - structfield.NewID("std", "net/url", "URL", "Fragment"), - structfield.NewID("std", "net/url", "URL", "RawFragment"), - structfield.NewID("std", "net/url", "URL", "Host"), - structfield.NewID("std", "net/url", "Userinfo", "username"), - structfield.NewID("std", "bufio", "Writer", "buf"), - structfield.NewID("std", "bufio", "Writer", "n"), - structfield.NewID("std", "net", "TCPAddr", "IP"), - structfield.NewID("std", "net", "TCPAddr", "Port"), + + // Added for Pixie's TLS tracing + structfield.NewID("std", "internal/poll", "FD", "Sysfd"), + structfield.NewID("std", "crypto/tls", "Conn", "conn"), + structfield.NewID("std", "net/http", "http2serverConn", "conn"), + structfield.NewID("std", "net/http", "http2serverConn", "hpackEncoder"), + structfield.NewID("std", "net/http", "http2HeadersFrame", "http2FrameHeader"), + structfield.NewID("std", "net/http", "http2FrameHeader", "Type"), + structfield.NewID("std", "net/http", "http2FrameHeader", "Flags"), + structfield.NewID("std", "net/http", "http2FrameHeader", "StreamID"), + structfield.NewID("std", "net/http", "http2DataFrame", "data"), + structfield.NewID("std", "net/http", "http2writeResHeaders", "streamID"), + structfield.NewID("std", "net/http", "http2writeResHeaders", "endStream"), + structfield.NewID("std", "net/http", "http2MetaHeadersFrame", "http2HeadersFrame"), + structfield.NewID("std", "net/http", "http2MetaHeadersFrame", "Fields"), + structfield.NewID("std", "net/http", "http2Framer", "w"), + // For Go 1.23 and earlier + structfield.NewID("std", "net/http", "http2bufferedWriter", "w"), + // For Go 1.24 and later + structfield.NewID("std", "net/http", "http2bufferedWriter", "conn"), + }, + }, + { + Application: inspect.Application{ + Renderer: ren("templates/net/http/*.tmpl"), + GoVerions: goVers, + }, + Funcs: []funcfield.ID{ + // net/http.(*http2Framer).WriteDataPadded + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2Framer).WriteDataPadded", + Arg: "f", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2Framer).WriteDataPadded", + Arg: "streamID", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2Framer).WriteDataPadded", + Arg: "endStream", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2Framer).WriteDataPadded", + Arg: "data", + }, + // net/http.(*http2Framer).checkFrameOrder + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2Framer).checkFrameOrder", + Arg: "fr", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2Framer).checkFrameOrder", + Arg: "f", + }, + // net/http.(*http2writeResHeaders).writeFrame + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2writeResHeaders).writeFrame", + Arg: "w", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2writeResHeaders).writeFrame", + Arg: "ctx", + }, + // net/http.(*http2serverConn).processHeaders + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2serverConn).processHeaders", + Arg: "sc", + }, + funcfield.ID{ + ModPath: "std", + PkgPath: "net/http", + Func: "(*http2serverConn).processHeaders", + Arg: "f", + }, }, }, { @@ -134,228 +243,158 @@ func manifests() ([]inspect.Manifest, error) { Versions: grpcVers, }, StructFields: []structfield.ID{ - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/transport", - "Stream", - "method", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/transport", - "Stream", - "id", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/transport", - "Stream", - "ctx", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/transport", - "ServerStream", - "Stream", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc", - "ClientConn", - "target", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/transport", - "http2Client", - "nextID", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/transport", - "headerFrame", - "streamID", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/transport", - "headerFrame", - "hf", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/status", - "Error", - "s", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/status", - "Status", - "s", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/genproto/googleapis/rpc/status", - "Status", - "Code", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/genproto/googleapis/rpc/status", - "Status", - "Message", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/internal/transport", - "http2Server", - "peer", - ), - structfield.NewID( - "google.golang.org/grpc", - "google.golang.org/grpc/peer", - "Peer", - "LocalAddr", - ), + + // Added for Pixie's GRPC tracing + structfield.NewID("google.golang.org/grpc", "google.golang.org/grpc/internal/transport", "http2Server", "conn"), + structfield.NewID("google.golang.org/grpc", "google.golang.org/grpc/internal/transport", "http2Client", "conn"), + structfield.NewID("google.golang.org/grpc", "google.golang.org/grpc/internal/transport", "loopyWriter", "framer"), + + // Added for Pixie's TLS tracing + structfield.NewID("google.golang.org/grpc", "google.golang.org/grpc/internal/transport", "bufWriter", "conn"), + + // TODO(ddelnano): This field is optional and when added to the offsetgen I'm not able to see the offsets be found. + // This may require adding this field to the templated application for it to work. + structfield.NewID("google.golang.org", "google.golang.org/grpc/credentials/internal", "syscallConn", "conn"), }, }, { Application: inspect.Application{ - Renderer: ren("templates/golang.org/x/net/*.tmpl"), - Versions: xNetVers, + Renderer: ren("templates/google.golang.org/grpc/*.tmpl"), + Versions: grpcVers, }, - StructFields: []structfield.ID{ - structfield.NewID( - "golang.org/x/net", - "golang.org/x/net/http2", - "MetaHeadersFrame", - "Fields", - ), - structfield.NewID( - "golang.org/x/net", - "golang.org/x/net/http2", - "FrameHeader", - "StreamID", - ), + Funcs: []funcfield.ID{ + // google.golang.org/grpc/internal/transport.(*http2Server).operateHeaders + funcfield.ID{ + ModPath: "google.golang.org/grpc", + PkgPath: "google.golang.org/grpc/internal/transport", + Func: "(*http2Server).operateHeaders", + Arg: "t", + }, + funcfield.ID{ + ModPath: "google.golang.org/grpc", + PkgPath: "google.golang.org/grpc/internal/transport", + Func: "(*http2Server).operateHeaders", + Arg: "frame", + }, + // google.golang.org/grpc/internal/transport.(*http2Client).operateHeaders + funcfield.ID{ + ModPath: "google.golang.org/grpc", + PkgPath: "google.golang.org/grpc/internal/transport", + Func: "(*http2Client).operateHeaders", + Arg: "t", + }, + funcfield.ID{ + ModPath: "google.golang.org/grpc", + PkgPath: "google.golang.org/grpc/internal/transport", + Func: "(*http2Client).operateHeaders", + Arg: "frame", + }, + // google.golang.org/grpc/internal/transport.(*loopyWriter).writeHeader + funcfield.ID{ + ModPath: "google.golang.org/grpc", + PkgPath: "google.golang.org/grpc/internal/transport", + Func: "(*loopyWriter).writeHeader", + Arg: "l", + }, + funcfield.ID{ + ModPath: "google.golang.org/grpc", + PkgPath: "google.golang.org/grpc/internal/transport", + Func: "(*loopyWriter).writeHeader", + Arg: "streamID", + }, + funcfield.ID{ + ModPath: "google.golang.org/grpc", + PkgPath: "google.golang.org/grpc/internal/transport", + Func: "(*loopyWriter).writeHeader", + Arg: "endStream", + }, + funcfield.ID{ + ModPath: "google.golang.org/grpc", + PkgPath: "google.golang.org/grpc/internal/transport", + Func: "(*loopyWriter).writeHeader", + Arg: "hf", + }, }, }, { Application: inspect.Application{ - Renderer: ren("templates/go.opentelemetry.io/otel/traceglobal/*.tmpl"), - Versions: goOtelVers, + Renderer: ren("templates/golang.org/x/net/*.tmpl"), + Versions: xNetVers, }, StructFields: []structfield.ID{ - structfield.NewID( - "go.opentelemetry.io/otel", - "go.opentelemetry.io/otel/internal/global", - "tracer", - "delegate", - ), - structfield.NewID( - "go.opentelemetry.io/otel", - "go.opentelemetry.io/otel/internal/global", - "tracer", - "name", - ), - structfield.NewID( - "go.opentelemetry.io/otel", - "go.opentelemetry.io/otel/internal/global", - "tracer", - "provider", - ), - structfield.NewID( - "go.opentelemetry.io/otel", - "go.opentelemetry.io/otel/internal/global", - "tracerProvider", - "tracers", - ), - structfield.NewID( - "go.opentelemetry.io/otel", - "go.opentelemetry.io/otel/trace", - "SpanContext", - "traceID", - ), - structfield.NewID( - "go.opentelemetry.io/otel", - "go.opentelemetry.io/otel/trace", - "SpanContext", - "spanID", - ), - structfield.NewID( - "go.opentelemetry.io/otel", - "go.opentelemetry.io/otel/trace", - "SpanContext", - "traceFlags", - ), + // Upstream but needed by Pixie's GRPC tracing + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2", "MetaHeadersFrame", "Fields"), + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2", "FrameHeader", "StreamID"), + + // Added for Pixie's GRPC tracing + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2/hpack", "HeaderField", "Name"), + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2/hpack", "HeaderField", "Value"), + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2/hpack", "HeaderField", "Value"), + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2", "MetaHeadersFrame", "HeadersFrame"), + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2", "HeadersFrame", "FrameHeader"), + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2", "FrameHeader", "Type"), + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2", "FrameHeader", "Flags"), + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2", "DataFrame", "data"), + structfield.NewID("golang.org/x/net", "golang.org/x/net/http2", "Framer", "w"), }, }, { Application: inspect.Application{ - Renderer: ren("templates/github.com/segmentio/kafka-go/*.tmpl"), - Versions: kafkaGoVers, + Renderer: ren("templates/golang.org/x/net/*.tmpl"), + Versions: xNetVers, }, - StructFields: []structfield.ID{ - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "Message", - "Topic", - ), - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "Message", - "Partition", - ), - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "Message", - "Offset", - ), - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "Message", - "Key", - ), - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "Message", - "Headers", - ), - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "Message", - "Time", - ), - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "Writer", - "Topic", - ), - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "Reader", - "config", - ), - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "ReaderConfig", - "GroupID", - ), - structfield.NewID( - "github.com/segmentio/kafka-go", - "github.com/segmentio/kafka-go", - "Conn", - "clientID", - ), + Funcs: []funcfield.ID{ + // golang.org/x/net/http2.(*Framer).WriteDataPadded + funcfield.ID{ + ModPath: "golang.org/x/net", + PkgPath: "golang.org/x/net/http2", + Func: "(*Framer).WriteDataPadded", + Arg: "f", + }, + funcfield.ID{ + ModPath: "golang.org/x/net", + PkgPath: "golang.org/x/net/http2", + Func: "(*Framer).WriteDataPadded", + Arg: "streamID", + }, + funcfield.ID{ + ModPath: "golang.org/x/net", + PkgPath: "golang.org/x/net/http2", + Func: "(*Framer).WriteDataPadded", + Arg: "endStream", + }, + funcfield.ID{ + ModPath: "golang.org/x/net", + PkgPath: "golang.org/x/net/http2", + Func: "(*Framer).WriteDataPadded", + Arg: "data", + }, + // golang.org/x/net/http2.(*Framer).checkFrameOrder + funcfield.ID{ + ModPath: "golang.org/x/net", + PkgPath: "golang.org/x/net/http2", + Func: "(*Framer).checkFrameOrder", + Arg: "fr", + }, + funcfield.ID{ + ModPath: "golang.org/x/net", + PkgPath: "golang.org/x/net/http2", + Func: "(*Framer).checkFrameOrder", + Arg: "f", + }, + // golang.org/x/net/http2/hpack.(*Encoder).WriteField + funcfield.ID{ + ModPath: "golang.org/x/net", + PkgPath: "golang.org/x/net/http2/hpack", + Func: "(*Encoder).WriteField", + Arg: "e", + }, + funcfield.ID{ + ModPath: "golang.org/x/net", + PkgPath: "golang.org/x/net/http2/hpack", + Func: "(*Encoder).WriteField", + Arg: "f", + }, }, }, }, nil diff --git a/internal/tools/inspect/inspector.go b/internal/tools/inspect/inspector.go index c6417fa07a..22a93888f4 100644 --- a/internal/tools/inspect/inspector.go +++ b/internal/tools/inspect/inspector.go @@ -6,12 +6,14 @@ package inspect import ( "context" "errors" + "fmt" "log/slog" "github.com/Masterminds/semver/v3" "github.com/docker/docker/client" "golang.org/x/sync/errgroup" + "go.opentelemetry.io/auto/internal/pkg/funcfield" "go.opentelemetry.io/auto/internal/pkg/structfield" ) @@ -79,11 +81,15 @@ func (i *Inspector) AddManifest(manifest Manifest) error { b := newBuilder(i.log, i.client, nil) for _, ver := range manifest.Application.Versions { v := ver + if len(manifest.StructFields) > 0 && len(manifest.Funcs) > 0 { + return errors.New("cannot use both struct fields and function fields in the same manifest") + } i.jobs = append(i.jobs, job{ Renderer: manifest.Application.Renderer, Builder: b, AppVer: v, Fields: manifest.StructFields, + Funcs: manifest.Funcs, }) } return nil @@ -92,11 +98,15 @@ func (i *Inspector) AddManifest(manifest Manifest) error { if manifest.Application.Versions == nil { for _, gVer := range goVer { v := gVer + if len(manifest.StructFields) > 0 && len(manifest.Funcs) > 0 { + return errors.New("cannot use both struct fields and function fields in the same manifest") + } i.jobs = append(i.jobs, job{ Renderer: manifest.Application.Renderer, Builder: newBuilder(i.log, i.client, v), AppVer: v, Fields: manifest.StructFields, + Funcs: manifest.Funcs, }) } return nil @@ -106,11 +116,15 @@ func (i *Inspector) AddManifest(manifest Manifest) error { b := newBuilder(i.log, i.client, gV) for _, ver := range manifest.Application.Versions { v := ver + if len(manifest.StructFields) > 0 && len(manifest.Funcs) > 0 { + return errors.New("cannot use both struct fields and function fields in the same manifest") + } i.jobs = append(i.jobs, job{ Renderer: manifest.Application.Renderer, Builder: b, AppVer: v, Fields: manifest.StructFields, + Funcs: manifest.Funcs, }) } } @@ -122,6 +136,12 @@ type job struct { Builder *builder AppVer *semver.Version Fields []structfield.ID + Funcs []funcfield.ID +} + +type result struct { + structs []stResult + fns []fnResult } // Do performs the inspections and returns all found offsets. @@ -141,7 +161,7 @@ func (i *Inspector) Do(ctx context.Context) (*structfield.Index, error) { return nil }) - c := make(chan []result) + c := make(chan result) for n := 0; n < max(1, i.NWorkers-1); n++ { g.Go(func() error { for m := range todo { @@ -166,11 +186,16 @@ func (i *Inspector) Do(ctx context.Context) (*structfield.Index, error) { index := structfield.NewIndex() for results := range c { - for _, r := range results { + for _, r := range results.structs { i.logResult(r) index.PutOffset(r.StructField, r.Version, r.Offset, r.Valid) } + for _, r := range results.fns { + i.logFuncResult(r) + + index.PutFuncOffset(r.FuncField, r.Version, r.Offset, r.Location, r.Valid) + } } if err := g.Wait(); err != nil { @@ -179,30 +204,55 @@ func (i *Inspector) Do(ctx context.Context) (*structfield.Index, error) { return index, nil } -type result struct { +type stResult struct { StructField structfield.ID + FuncField funcfield.ID + Location funcfield.Location Version *semver.Version Offset uint64 // Valid is true if the offset is valid for the struct field at the specified version. Valid bool } -func (i *Inspector) do(ctx context.Context, j job) (out []result, err error) { - var uncachedIndices []int +type fnResult struct { + FuncField funcfield.ID + Location funcfield.Location + Version *semver.Version + Offset uint64 + // Valid is true if the offset is valid for the struct field at the specified version. + Valid bool +} + +func (i *Inspector) do(ctx context.Context, j job) (out result, err error) { + var uncachedStructIndices []int + var uncachedFuncIndices []int for _, f := range j.Fields { o, ok := i.Cache.GetOffset(j.AppVer, f) - out = append(out, result{ + out.structs = append(out.structs, stResult{ StructField: f, Version: j.AppVer, Offset: o.Offset, Valid: o.Valid, }) if !ok { - uncachedIndices = append(uncachedIndices, len(out)-1) + uncachedStructIndices = append(uncachedStructIndices, len(out.structs)-1) } } - if len(uncachedIndices) == 0 { + for _, f := range j.Funcs { + o, ok := i.Cache.GetFuncOffset(j.AppVer, f) + out.fns = append(out.fns, fnResult{ + FuncField: f, + Version: j.AppVer, + Offset: o.Offset, + Valid: o.Valid, + Location: o.Location, + }) + if !ok { + uncachedFuncIndices = append(uncachedFuncIndices, len(out.fns)-1) + } + } + if len(uncachedStructIndices) == 0 && len(uncachedFuncIndices) == 0 { return out, nil } @@ -220,18 +270,23 @@ func (i *Inspector) do(ctx context.Context, j job) (out []result, err error) { ) return out, nil } else if err != nil { - return nil, err + return out, err } defer app.Close() - for _, i := range uncachedIndices { - out[i].Offset, out[i].Valid = app.GetOffset(out[i].StructField) + for _, i := range uncachedStructIndices { + out.structs[i].Offset, out.structs[i].Valid = app.GetOffset(out.structs[i].StructField) + } + + for _, i := range uncachedFuncIndices { + fmt.Printf("uncachedFuncIndices: %d for %+v\n", i, out.fns[i].FuncField) + out.fns[i].Offset, out.fns[i].Location, out.fns[i].Valid = app.GetFuncArgs(out.fns[i].FuncField) } return out, nil } -func (i *Inspector) logResult(r result) { +func (i *Inspector) logResult(r stResult) { msg := "offset " kv := []interface{}{"version", r.Version, "id", r.StructField} if !r.Valid { @@ -242,3 +297,15 @@ func (i *Inspector) logResult(r result) { } i.log.Info(msg, kv...) } + +func (i *Inspector) logFuncResult(r fnResult) { + msg := "offset " + kv := []interface{}{"version", r.Version, "id", r.FuncField, "location", r.Location} + if !r.Valid { + msg += "not found" + } else { + msg += "found" + kv = append(kv, "offset", r.Offset) + } + i.log.Info(msg, kv...) +} diff --git a/internal/tools/inspect/manifest.go b/internal/tools/inspect/manifest.go index 0d58ca1fee..8722974c38 100644 --- a/internal/tools/inspect/manifest.go +++ b/internal/tools/inspect/manifest.go @@ -8,6 +8,7 @@ import ( "github.com/Masterminds/semver/v3" + "go.opentelemetry.io/auto/internal/pkg/funcfield" "go.opentelemetry.io/auto/internal/pkg/structfield" ) @@ -19,6 +20,7 @@ type Manifest struct { // StructFields are struct fields the application should contain that need // offsets to be found. StructFields []structfield.ID + Funcs []funcfield.ID } func (m Manifest) validate() error { diff --git a/internal/tools/inspect/render.go b/internal/tools/inspect/render.go index 3933b2f250..cac1e2ded5 100644 --- a/internal/tools/inspect/render.go +++ b/internal/tools/inspect/render.go @@ -19,6 +19,7 @@ import ( //go:embed templates/golang.org/x/net/*.tmpl //go:embed templates/google.golang.org/grpc/*.tmpl //go:embed templates/net/http/*.tmpl +//go:embed templates/crypto/tls/*.tmpl //go:embed templates/runtime/*.tmpl //go:embed templates/go.opentelemetry.io/otel/traceglobal/*.tmpl //go:embed templates/github.com/segmentio/kafka-go/*.tmpl @@ -48,7 +49,7 @@ func NewRenderer(l *slog.Logger, src string, f fs.FS) Renderer { // All src will be rendered in the same file-tree with the same names (except // for any ".tmpl" suffixes) as found in the Renderer's fs.FS. func (r Renderer) Render(dest string, data interface{}) error { - r.log.Debug("rendering...", "src", r.src, "dest", dest, "data", data) + r.log.Info("rendering...", "src", r.src, "dest", dest, "data", data) tmpls, err := template.ParseFS(r.fs, r.src) if err != nil { diff --git a/internal/tools/inspect/templates/crypto/tls/go.mod.tmpl b/internal/tools/inspect/templates/crypto/tls/go.mod.tmpl new file mode 100644 index 0000000000..b46adc1e96 --- /dev/null +++ b/internal/tools/inspect/templates/crypto/tls/go.mod.tmpl @@ -0,0 +1,3 @@ +module netapp + +go 1.19 diff --git a/internal/tools/inspect/templates/crypto/tls/https_server.go.tmpl b/internal/tools/inspect/templates/crypto/tls/https_server.go.tmpl new file mode 100644 index 0000000000..52000ac144 --- /dev/null +++ b/internal/tools/inspect/templates/crypto/tls/https_server.go.tmpl @@ -0,0 +1,63 @@ +/* + * Copyright 2018- The Pixie Authors. + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package main + +import ( + "fmt" + "io" + "log" + "net/http" +) + +const ( + httpPort = 50100 + httpsPort = 50101 +) + +func basicHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Content-Type", "application/json") + _, err := io.WriteString(w, `{"status":"ok"}`) + if err != nil { + log.Fatal(err) + } +} + +func listenAndServeTLS(port int, certFile, keyFile string) { + log.Printf("Starting HTTPS service on Port %d", port) + err := http.ListenAndServeTLS(fmt.Sprintf(":%d", port), certFile, keyFile, nil) + if err != nil { + log.Fatal(err) + } +} + +func listenAndServe(port int) { + log.Printf("Starting HTTP service on Port %d", port) + err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil) + if err != nil { + log.Fatal(err) + } +} + +func main() { + + http.HandleFunc("/", basicHandler) + + go listenAndServeTLS(httpsPort, "cert.crt", "private.key") + listenAndServe(httpPort) +} diff --git a/internal/tools/inspect/templates/golang.org/x/net/main.go.tmpl b/internal/tools/inspect/templates/golang.org/x/net/main.go.tmpl index 72a9f3fa80..e3551796df 100644 --- a/internal/tools/inspect/templates/golang.org/x/net/main.go.tmpl +++ b/internal/tools/inspect/templates/golang.org/x/net/main.go.tmpl @@ -1,8 +1,29 @@ package main -import "golang.org/x/net/http2" +import ( + "fmt" + "log" + "net/http" + + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" +) func main() { - var mhf http2.MetaHeadersFrame - _ = mhf.HeadersEnded() + // A trivial handler that reports the protocol that reached it. + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello! Path=%s • Protocol=%s\n", r.URL.Path, r.Proto) + }) + + // Wrap the handler so it speaks h2c (clear-text HTTP/2). + h2s := &http2.Server{} + srv := &http.Server{ + Addr: ":8080", + Handler: h2c.NewHandler(handler, h2s), + } + + log.Printf("h2c server listening on http://localhost:8080 …") + if err := srv.ListenAndServe(); err != nil { + log.Fatalf("server error: %v", err) + } } diff --git a/internal/tools/inspect/templates/net/http/go.mod.tmpl b/internal/tools/inspect/templates/net/http/go.mod.tmpl index b46adc1e96..b786178238 100644 --- a/internal/tools/inspect/templates/net/http/go.mod.tmpl +++ b/internal/tools/inspect/templates/net/http/go.mod.tmpl @@ -1,3 +1,24 @@ -module netapp +module http2app go 1.19 + +require ( + github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.8.1 +) + +require ( + github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/magiconair/properties v1.8.5 // indirect + github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/pelletier/go-toml v1.9.3 // indirect + github.com/spf13/afero v1.6.0 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + gopkg.in/ini.v1 v1.62.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/internal/tools/inspect/templates/net/http/main.go.tmpl b/internal/tools/inspect/templates/net/http/main.go.tmpl index 40100bb82d..2cfef443d8 100644 --- a/internal/tools/inspect/templates/net/http/main.go.tmpl +++ b/internal/tools/inspect/templates/net/http/main.go.tmpl @@ -1,13 +1,62 @@ +/* + * Copyright 2018- The Pixie Authors. + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + package main import ( - "net" + "fmt" + "io" + "log" "net/http" ) +const ( + httpPort = 50100 + httpsPort = 50101 +) + +func basicHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Content-Type", "application/json") + _, err := io.WriteString(w, `{"status":"ok"}`) + if err != nil { + log.Fatal(err) + } +} + +func listenAndServeTLS(port int, certFile, keyFile string) { + log.Printf("Starting HTTPS service on Port %d", port) + err := http.ListenAndServeTLS(fmt.Sprintf(":%d", port), certFile, keyFile, nil) + if err != nil { + log.Fatal(err) + } +} + +func listenAndServe(port int) { + log.Printf("Starting HTTP service on Port %d", port) + err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil) + if err != nil { + log.Fatal(err) + } +} + func main() { - addr := net.TCPAddr{Port: 1234} - http.ListenAndServe(addr.String(), http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { - writer.WriteHeader(request.ProtoMajor) - })) + http.HandleFunc("/", basicHandler) + + go listenAndServeTLS(httpsPort, "cert", "key") + listenAndServe(httpPort) } diff --git a/main.py b/main.py new file mode 100644 index 0000000000..e5ec34eaa0 --- /dev/null +++ b/main.py @@ -0,0 +1,214 @@ +import argparse +import json +import sys +import os + +def transform_offset_results_flat(input_path, output_path): + with open(input_path, 'r') as f: + data = json.load(f) + + # This will hold the final transformed data. + # + # Example structure of "result" when finished: + # { + # "golang.org/x/net/http2.DataFrame": { + # "data": { + # "0.1.0": null, + # "0.2.0": null, + # ... + # } + # }, + # "golang.org/x/net/http2.FrameHeader": { + # "Flags": { + # "0.1.0": 2, + # ... + # }, + # ... + # }, + # "crypto/tls.(*Conn).Read": { + # "b": { + # "1.19.0": { + # "location": "registers", + # "offset": 8 + # }, + # "1.19.1": ... + # }, + # "c": {...}, + # } + # ... + # } + # + # Each of those top-level keys aggregates the fields (for structs) + # or arguments (for funcs) under it. + + result = {} + + for module_entry in data: + # e.g. "golang.org/x/net" + module_name = module_entry["module"] + + for pkg in module_entry["packages"]: + # e.g. "golang.org/x/net/http2" + package_name = pkg["package"] + + # Handle all structs + if "structs" in pkg and pkg["structs"]: + for st in pkg["structs"]: + struct_name = st["struct"] # e.g. "DataFrame" + struct_key = f"{package_name}.{struct_name}" + # Ensure we have an entry for this struct + if struct_key not in result: + result[struct_key] = {} + + # Each struct can have multiple fields + for field in st["fields"]: + field_name = field["field"] + if field_name not in result[struct_key]: + result[struct_key][field_name] = {} + + # Each field can have multiple “offset” groups, each specifying certain versions + for off_obj in field["offsets"]: + offset_val = off_obj["offset"] + location_val = off_obj.get("location", None) + + # Assign this offset (or offset object) to all listed versions + for ver in off_obj["versions"]: + if location_val and location_val.lower() != "unknown": + # Store as an object with location + offset + result[struct_key][field_name][ver] = { + "location": location_val, + "offset": offset_val + } + else: + # If no special location, just store the offset (possibly null) + result[struct_key][field_name][ver] = offset_val + + # Handle all funcs + if "funcs" in pkg and pkg["funcs"]: + for fn in pkg["funcs"]: + func_name = fn["func"] # e.g. "(*Encoder).WriteField" + func_key = f"{package_name}.{func_name}" + # Ensure we have an entry for this function + if func_key not in result: + result[func_key] = {} + + # Each function can have multiple arguments + for arg in fn["args"]: + arg_name = arg["arg"] + if arg_name not in result[func_key]: + result[func_key][arg_name] = {} + + for off_obj in arg["offsets"]: + offset_val = off_obj["offset"] + location_val = off_obj.get("location", None) + + for ver in off_obj["versions"]: + if location_val and location_val.lower() != "unknown": + result[func_key][arg_name][ver] = { + "location": location_val, + "offset": offset_val + } + else: + result[func_key][arg_name][ver] = offset_val + + # Write the final output as JSON + with open(output_path, 'w') as out_f: + json.dump(result, out_f, indent=2) + + +def main(): + parser = argparse.ArgumentParser( + description="Transform offset_results.json into either a flat or nested format." + ) + parser.add_argument("input_file", help="Path to the input JSON file (offset_results.json).") + parser.add_argument("output_file", help="Path to the transformed output JSON file.") + parser.add_argument( + "--mode", + choices=["flat", "nested"], + default="flat", + help="Select the transformation mode: 'flat' for top-level keys, 'nested' for top-level 'structs' and 'funcs'." + ) + + args = parser.parse_args() + + if args.mode == "nested": + transform_offset_results_nested(args.input_file, args.output_file) + print(f"Transformed (nested) JSON written to {args.output_file}") + else: + transform_offset_results_flat(args.input_file, args.output_file) + print(f"Transformed (flat) JSON written to {args.output_file}") + +def transform_offset_results_nested(input_path, output_path): + with open(input_path, 'r') as f: + data = json.load(f) + + # We'll separate everything into top-level "structs" and "funcs" + result = { + "structs": {}, + "funcs": {} + } + + for module_entry in data: + for pkg in module_entry["packages"]: + package_name = pkg["package"] + + # Process structs + if "structs" in pkg and pkg["structs"]: + for st in pkg["structs"]: + struct_name = st["struct"] + struct_key = f"{package_name}.{struct_name}" + + if struct_key not in result["structs"]: + result["structs"][struct_key] = {} + + for field in st["fields"]: + field_name = field["field"] + if field_name not in result["structs"][struct_key]: + result["structs"][struct_key][field_name] = {} + + for off_obj in field["offsets"]: + offset_val = off_obj["offset"] + location_val = off_obj.get("location", None) + + for ver in off_obj["versions"]: + if location_val and location_val.lower() != "unknown": + result["structs"][struct_key][field_name][ver] = { + "location": location_val, + "offset": offset_val + } + else: + result["structs"][struct_key][field_name][ver] = offset_val + + # Process funcs + if "funcs" in pkg and pkg["funcs"]: + for fn in pkg["funcs"]: + func_name = fn["func"] + func_key = f"{package_name}.{func_name}" + + if func_key not in result["funcs"]: + result["funcs"][func_key] = {} + + for arg in fn["args"]: + arg_name = arg["arg"] + if arg_name not in result["funcs"][func_key]: + result["funcs"][func_key][arg_name] = {} + + for off_obj in arg["offsets"]: + offset_val = off_obj["offset"] + location_val = off_obj.get("location", None) + + for ver in off_obj["versions"]: + if location_val and location_val.lower() != "unknown": + result["funcs"][func_key][arg_name][ver] = { + "location": location_val, + "offset": offset_val + } + else: + result["funcs"][func_key][arg_name][ver] = offset_val + + with open(output_path, 'w') as out_f: + json.dump(result, out_f, indent=2) + +if __name__ == "__main__": + main() + diff --git a/sdk/internal/telemetry/test/go.mod b/sdk/internal/telemetry/test/go.mod index 4654264a36..b4f8150f81 100644 --- a/sdk/internal/telemetry/test/go.mod +++ b/sdk/internal/telemetry/test/go.mod @@ -20,7 +20,7 @@ require ( golang.org/x/net v0.40.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/text v0.25.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect google.golang.org/grpc v1.72.2 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/sdk/internal/telemetry/test/go.sum b/sdk/internal/telemetry/test/go.sum index a58bd19a34..baf71a919a 100644 --- a/sdk/internal/telemetry/test/go.sum +++ b/sdk/internal/telemetry/test/go.sum @@ -85,8 +85,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8= google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=