diff --git a/ebpf/Makefile b/ebpf/Makefile index c555590968..5aaa49de77 100644 --- a/ebpf/Makefile +++ b/ebpf/Makefile @@ -1,6 +1,6 @@ GO ?= go -RIDESHARE_REPO ?= korniltsev -RIDESHARE="testdata/rideshare-flask-no-pip" +RIDESHARE_REPO ?= pyroscope +RIDESHARE=testdata/rideshare-flask-no-pip ifeq ($(shell uname -s),Linux) ifeq ($(shell uname -m),x86_64) @@ -29,12 +29,12 @@ python/dwarfdump: git submodule update --init --recursive echo "//go:build amd64 && linux" > python/python_offsets_gen_amd64.go - go run cmd/python_dwarfdump/main.go $(shell find testdata/python-x64 -name libpy\*.so\*) \ + go run cmd/python_dwarfdump/main.go $(shell find testdata/python-x64 -name libpy\*.so\* | grep -v pyston) \ $(shell find testdata/python-x64 | grep -E "/python3\\.[0-9]+") >> python/python_offsets_gen_amd64.go go fmt python/python_offsets_gen_amd64.go echo "//go:build arm64 && linux" > python/python_offsets_gen_arm64.go - go run cmd/python_dwarfdump/main.go $(shell find testdata/python-arm64 -name libpy\*.so\*) \ + go run cmd/python_dwarfdump/main.go $(shell find testdata/python-arm64 -name libpy\*.so\* | grep -v pyston) \ $(shell find testdata/python-arm64 | grep -E "/python3\\.[0-9]+") >> python/python_offsets_gen_arm64.go go fmt python/python_offsets_gen_arm64.go @@ -104,4 +104,6 @@ rideshare/gen: docker buildx build --platform=linux/amd64,linux/arm64 --push -t $(RIDESHARE_REPO)/ebpf-testdata-rideshare:3.10-alpine --build-arg="PYTHON_VERSION=3.10-alpine" $(RIDESHARE) docker buildx build --platform=linux/amd64,linux/arm64 --push -t $(RIDESHARE_REPO)/ebpf-testdata-rideshare:3.11-alpine --build-arg="PYTHON_VERSION=3.11-alpine" $(RIDESHARE) docker buildx build --platform=linux/amd64,linux/arm64 --push -t $(RIDESHARE_REPO)/ebpf-testdata-rideshare:3.12-alpine --build-arg="PYTHON_VERSION=3.12-alpine" $(RIDESHARE) - docker buildx build --platform=linux/amd64,linux/arm64 --push -t $(RIDESHARE_REPO)/ebpf-testdata-rideshare:3.13-rc-alpine --build-arg="PYTHON_VERSION=3.13-rc-alpine" $(RIDESHARE) \ No newline at end of file + docker buildx build --platform=linux/amd64,linux/arm64 --push -t $(RIDESHARE_REPO)/ebpf-testdata-rideshare:3.13-rc-alpine --build-arg="PYTHON_VERSION=3.13-rc-alpine" $(RIDESHARE) + docker buildx build --platform=linux/amd64,linux/arm64 --push -t $(RIDESHARE_REPO)/ebpf-testdata-rideshare:ubuntu-20.04 --build-arg="BASE=ubuntu:20.04" --build-arg="FLASK_VERSION=3.0.3" -f $(RIDESHARE)/ubuntu.Dockerfile $(RIDESHARE) + docker buildx build --platform=linux/amd64,linux/arm64 --push -t $(RIDESHARE_REPO)/ebpf-testdata-rideshare:ubuntu-22.04 --build-arg="BASE=ubuntu:22.04" --build-arg="FLASK_VERSION=3.0.3" -f $(RIDESHARE)/ubuntu.Dockerfile $(RIDESHARE) diff --git a/ebpf/cmd/python_dwarfdump/main.go b/ebpf/cmd/python_dwarfdump/main.go index 63216fd8e8..9e2481c069 100644 --- a/ebpf/cmd/python_dwarfdump/main.go +++ b/ebpf/cmd/python_dwarfdump/main.go @@ -66,7 +66,7 @@ var pythonFields = []dwarfdump.Need{ {Name: "_typeobject", PrettyName: "PyTypeObject", Fields: []dwarfdump.NeedField{ {"tp_name", "PyTypeObject_tp_name"}, }}, - {Name: "PyThreadState", Fields: []dwarfdump.NeedField{ + {Name: "_ts", Fields: []dwarfdump.NeedField{ {"frame", "PyThreadState_frame"}, {"cframe", "PyThreadState_cframe"}, {"current_frame", "PyThreadState_current_frame"}, diff --git a/ebpf/dwarfdump/dwarfdump.go b/ebpf/dwarfdump/dwarfdump.go index a62aae83c0..d96247e8dc 100644 --- a/ebpf/dwarfdump/dwarfdump.go +++ b/ebpf/dwarfdump/dwarfdump.go @@ -4,6 +4,7 @@ import ( "debug/dwarf" "debug/elf" "fmt" + "os" "reflect" "strings" ) @@ -193,6 +194,7 @@ type FieldDump struct { } func Dump(elfPath string, fields []Need) []FieldDump { + fmt.Fprintf(os.Stderr, "Dumping %s\n", elfPath) var err error f, err := elf.Open(elfPath) diff --git a/ebpf/python/procinfo.go b/ebpf/python/procinfo.go index 56033beea5..7873e97aaa 100644 --- a/ebpf/python/procinfo.go +++ b/ebpf/python/procinfo.go @@ -3,6 +3,7 @@ package python import ( "bufio" "fmt" + "path/filepath" "regexp" "strconv" "strings" @@ -58,7 +59,7 @@ func GetProcInfo(s *bufio.Scanner) (ProcInfo, error) { strings.Contains(m.Pathname, "/lib/ld-musl-aarch64.so.1") { res.Musl = append(res.Musl, m) } - if strings.HasSuffix(m.Pathname, "/libc.so.6") || strings.HasSuffix(m.Pathname, "/libc-2") { + if strings.HasSuffix(m.Pathname, "/libc.so.6") || strings.HasPrefix(filepath.Base(m.Pathname), "libc-2.") { res.Glibc = append(res.Glibc, m) } } diff --git a/ebpf/python/procinfo_test.go b/ebpf/python/procinfo_test.go index e477dbe0cb..8474ab4bef 100644 --- a/ebpf/python/procinfo_test.go +++ b/ebpf/python/procinfo_test.go @@ -56,6 +56,7 @@ ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsysca info, err := GetProcInfo(bufio.NewScanner(bytes.NewReader([]byte(maps)))) require.NoError(t, err) require.Nil(t, info.Musl) + require.NotNil(t, info.Glibc) require.Equal(t, info.Version, Version{3, 6, 0}) require.NotNil(t, info.PythonMaps) require.NotNil(t, info.LibPythonMaps) @@ -116,6 +117,7 @@ ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsysca info, err = GetProcInfo(bufio.NewScanner(bytes.NewReader([]byte(maps)))) require.NoError(t, err) require.NotNil(t, info.Musl) + require.Nil(t, info.Glibc) require.Equal(t, info.Version, Version{3, 11, 0}) require.NotNil(t, info.PythonMaps) require.NotNil(t, info.LibPythonMaps) @@ -128,6 +130,7 @@ ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsysca info, err = GetProcInfo(bufio.NewScanner(bytes.NewReader([]byte(maps)))) require.NoError(t, err) require.Nil(t, info.Musl) + require.Nil(t, info.Glibc) require.Equal(t, info.Version, Version{3, 7, 0}) require.NotNil(t, info.PythonMaps) require.Nil(t, info.LibPythonMaps) @@ -160,6 +163,7 @@ fffff8c25000-fffff8c53000 rw-p 00000000 00:00 0 [stack] info, err = GetProcInfo(bufio.NewScanner(bytes.NewReader([]byte(maps)))) require.NoError(t, err) require.Nil(t, info.Musl) + require.NotNil(t, info.Glibc) require.Equal(t, info.Version, Version{3, 8, 0}) require.Nil(t, info.PythonMaps) require.NotNil(t, info.LibPythonMaps) diff --git a/ebpf/python/python_offsets_gen_amd64.go b/ebpf/python/python_offsets_gen_amd64.go index 7fa8456d3b..1ae50dfd19 100644 --- a/ebpf/python/python_offsets_gen_amd64.go +++ b/ebpf/python/python_offsets_gen_amd64.go @@ -3352,14 +3352,14 @@ var pyVersions = map[Version]*UserOffsets{ PyASCIIObjectSize: 40, PyCompactUnicodeObjectSize: 56, }, - // 3.13.0 testdata/python-x64/3.13.0a4/libpython3.13.so.1.0 + // 3.13.0 testdata/python-x64/3.13.0a6/libpython3.13.so.1.0 {3, 13, 0}: { PyVarObject_ob_size: 16, PyObject_ob_type: 8, PyTypeObject_tp_name: 24, PyThreadState_frame: -1, PyThreadState_cframe: -1, - PyThreadState_current_frame: 64, + PyThreadState_current_frame: 72, PyCFrame_current_frame: -1, PyFrameObject_f_back: 16, PyFrameObject_f_code: -1, @@ -3374,8 +3374,8 @@ var pyVersions = map[Version]*UserOffsets{ PyInterpreterFrame_previous: 8, PyInterpreterFrame_localsplus: 72, PyInterpreterFrame_owner: 70, - PyRuntimeState_gilstate: 3128, - PyRuntimeState_autoTSSkey: 1864, + PyRuntimeState_gilstate: 3160, + PyRuntimeState_autoTSSkey: 1896, Gilstate_runtime_state_autoTSSkey: -1, PyTssT_is_initialized: 0, PyTssT_key: 4, diff --git a/ebpf/python/python_offsets_gen_arm64.go b/ebpf/python/python_offsets_gen_arm64.go index 6f55a813f3..accaff37a7 100644 --- a/ebpf/python/python_offsets_gen_arm64.go +++ b/ebpf/python/python_offsets_gen_arm64.go @@ -3352,14 +3352,14 @@ var pyVersions = map[Version]*UserOffsets{ PyASCIIObjectSize: 40, PyCompactUnicodeObjectSize: 56, }, - // 3.13.0 testdata/python-arm64/3.13.0a4/libpython3.13.so.1.0 + // 3.13.0 testdata/python-arm64/3.13.0a6/libpython3.13.so.1.0 {3, 13, 0}: { PyVarObject_ob_size: 16, PyObject_ob_type: 8, PyTypeObject_tp_name: 24, PyThreadState_frame: -1, PyThreadState_cframe: -1, - PyThreadState_current_frame: 64, + PyThreadState_current_frame: 72, PyCFrame_current_frame: -1, PyFrameObject_f_back: 16, PyFrameObject_f_code: -1, @@ -3374,39 +3374,8 @@ var pyVersions = map[Version]*UserOffsets{ PyInterpreterFrame_previous: 8, PyInterpreterFrame_localsplus: 72, PyInterpreterFrame_owner: 70, - PyRuntimeState_gilstate: 3128, - PyRuntimeState_autoTSSkey: 1864, - Gilstate_runtime_state_autoTSSkey: -1, - PyTssT_is_initialized: 0, - PyTssT_key: 4, - PyTssTSize: 8, - PyASCIIObjectSize: 40, - PyCompactUnicodeObjectSize: 56, - }, - // 3.13.0 testdata/python-arm64/3.13.0a1/lib/libpython3.13.so.1.0 - {3, 13, 0}: { - PyVarObject_ob_size: 16, - PyObject_ob_type: 8, - PyTypeObject_tp_name: 24, - PyThreadState_frame: -1, - PyThreadState_cframe: -1, - PyThreadState_current_frame: 64, - PyCFrame_current_frame: -1, - PyFrameObject_f_back: 16, - PyFrameObject_f_code: -1, - PyFrameObject_f_localsplus: -1, - PyCodeObject_co_filename: 112, - PyCodeObject_co_name: 120, - PyCodeObject_co_varnames: -1, - PyCodeObject_co_localsplusnames: 96, - PyTupleObject_ob_item: 24, - PyInterpreterFrame_f_code: -1, - PyInterpreterFrame_f_executable: 0, - PyInterpreterFrame_previous: 8, - PyInterpreterFrame_localsplus: 72, - PyInterpreterFrame_owner: 70, - PyRuntimeState_gilstate: 3112, - PyRuntimeState_autoTSSkey: 1848, + PyRuntimeState_gilstate: 3160, + PyRuntimeState_autoTSSkey: 1896, Gilstate_runtime_state_autoTSSkey: -1, PyTssT_is_initialized: 0, PyTssT_key: 4, diff --git a/ebpf/python3_ebpf_expected.txt b/ebpf/python3_ebpf_expected.txt new file mode 100644 index 0000000000..c723bd6e5a --- /dev/null +++ b/ebpf/python3_ebpf_expected.txt @@ -0,0 +1,4 @@ +python3;server.py ;app.py Flask.run;serving.py run_simple;serving.py BaseWSGIServer.serve_forever;socketserver.py BaseWSGIServer.serve_forever;socketserver.py BaseWSGIServer._handle_request_noblock;socketserver.py BaseWSGIServer.process_request;socketserver.py BaseWSGIServer.finish_request;socketserver.py WSGIRequestHandler.__init__;serving.py WSGIRequestHandler.handle;server.py WSGIRequestHandler.handle;server.py WSGIRequestHandler.handle_one_request;serving.py NullCls.run_wsgi;serving.py execute;app.py Flask.__call__;app.py Flask.wsgi_app;app.py Flask.full_dispatch_request;app.py Flask.dispatch_request;server.py bike;bike.py order_bike;utility.py find_nearest_vehicle +python3;server.py ;app.py Flask.run;serving.py run_simple;serving.py BaseWSGIServer.serve_forever;socketserver.py BaseWSGIServer.serve_forever;socketserver.py BaseWSGIServer._handle_request_noblock;socketserver.py BaseWSGIServer.process_request;socketserver.py BaseWSGIServer.finish_request;socketserver.py WSGIRequestHandler.__init__;serving.py WSGIRequestHandler.handle;server.py WSGIRequestHandler.handle;server.py WSGIRequestHandler.handle_one_request;serving.py NullCls.run_wsgi;serving.py execute;app.py Flask.__call__;app.py Flask.wsgi_app;app.py Flask.full_dispatch_request;app.py Flask.dispatch_request;server.py car;car.py order_car;utility.py find_nearest_vehicle +python3;server.py ;app.py Flask.run;serving.py run_simple;serving.py BaseWSGIServer.serve_forever;socketserver.py BaseWSGIServer.serve_forever;socketserver.py BaseWSGIServer._handle_request_noblock;socketserver.py BaseWSGIServer.process_request;socketserver.py BaseWSGIServer.finish_request;socketserver.py WSGIRequestHandler.__init__;serving.py WSGIRequestHandler.handle;server.py WSGIRequestHandler.handle;server.py WSGIRequestHandler.handle_one_request;serving.py NullCls.run_wsgi;serving.py execute;app.py Flask.__call__;app.py Flask.wsgi_app;app.py Flask.full_dispatch_request;app.py Flask.dispatch_request;server.py car;car.py order_car;utility.py find_nearest_vehicle;utility.py check_driver_availability +python3;server.py ;app.py Flask.run;serving.py run_simple;serving.py BaseWSGIServer.serve_forever;socketserver.py BaseWSGIServer.serve_forever;socketserver.py BaseWSGIServer._handle_request_noblock;socketserver.py BaseWSGIServer.process_request;socketserver.py BaseWSGIServer.finish_request;socketserver.py WSGIRequestHandler.__init__;serving.py WSGIRequestHandler.handle;server.py WSGIRequestHandler.handle;server.py WSGIRequestHandler.handle_one_request;serving.py NullCls.run_wsgi;serving.py execute;app.py Flask.__call__;app.py Flask.wsgi_app;app.py Flask.full_dispatch_request;app.py Flask.dispatch_request;server.py scooter;scooter.py order_scooter;utility.py find_nearest_vehicle \ No newline at end of file diff --git a/ebpf/python_ebpf_test.go b/ebpf/python_ebpf_test.go index 07ca3c7604..8f99470487 100644 --- a/ebpf/python_ebpf_test.go +++ b/ebpf/python_ebpf_test.go @@ -25,23 +25,28 @@ var pythonEBPFExpected []byte //go:embed python_ebpf_expected_3.11.txt var pythonEBPFExpected311 []byte +//go:embed python3_ebpf_expected.txt +var python3EBPFExpected []byte + func TestEBPFPythonProfiler(t *testing.T) { var testdata = []struct { image string expected []byte }{ - {"korniltsev/ebpf-testdata-rideshare:3.8-slim", pythonEBPFExpected}, - {"korniltsev/ebpf-testdata-rideshare:3.9-slim", pythonEBPFExpected}, - {"korniltsev/ebpf-testdata-rideshare:3.10-slim", pythonEBPFExpected}, - {"korniltsev/ebpf-testdata-rideshare:3.11-slim", pythonEBPFExpected311}, - {"korniltsev/ebpf-testdata-rideshare:3.12-slim", pythonEBPFExpected311}, - {"korniltsev/ebpf-testdata-rideshare:3.13-rc-slim", pythonEBPFExpected311}, - {"korniltsev/ebpf-testdata-rideshare:3.8-alpine", pythonEBPFExpected}, - {"korniltsev/ebpf-testdata-rideshare:3.9-alpine", pythonEBPFExpected}, - {"korniltsev/ebpf-testdata-rideshare:3.10-alpine", pythonEBPFExpected}, - {"korniltsev/ebpf-testdata-rideshare:3.11-alpine", pythonEBPFExpected311}, - {"korniltsev/ebpf-testdata-rideshare:3.12-alpine", pythonEBPFExpected311}, - {"korniltsev/ebpf-testdata-rideshare:3.13-rc-alpine", pythonEBPFExpected311}, + {"pyroscope/ebpf-testdata-rideshare:3.8-slim", pythonEBPFExpected}, + {"pyroscope/ebpf-testdata-rideshare:3.9-slim", pythonEBPFExpected}, + {"pyroscope/ebpf-testdata-rideshare:3.10-slim", pythonEBPFExpected}, + {"pyroscope/ebpf-testdata-rideshare:3.11-slim", pythonEBPFExpected311}, + {"pyroscope/ebpf-testdata-rideshare:3.12-slim", pythonEBPFExpected311}, + {"pyroscope/ebpf-testdata-rideshare:3.13-rc-slim", pythonEBPFExpected311}, + {"pyroscope/ebpf-testdata-rideshare:3.8-alpine", pythonEBPFExpected}, + {"pyroscope/ebpf-testdata-rideshare:3.9-alpine", pythonEBPFExpected}, + {"pyroscope/ebpf-testdata-rideshare:3.10-alpine", pythonEBPFExpected}, + {"pyroscope/ebpf-testdata-rideshare:3.11-alpine", pythonEBPFExpected311}, + {"pyroscope/ebpf-testdata-rideshare:3.12-alpine", pythonEBPFExpected311}, + {"pyroscope/ebpf-testdata-rideshare:3.13-rc-alpine", pythonEBPFExpected311}, + {"pyroscope/ebpf-testdata-rideshare:ubuntu-20.04", python3EBPFExpected}, + {"pyroscope/ebpf-testdata-rideshare:ubuntu-22.04", python3EBPFExpected}, } const ridesharePort = "5000" diff --git a/ebpf/symtab/elf/buildid.go b/ebpf/symtab/elf/buildid.go index 8ce993d98c..4ed79b96d6 100644 --- a/ebpf/symtab/elf/buildid.go +++ b/ebpf/symtab/elf/buildid.go @@ -93,7 +93,7 @@ func (f *MMapedElfFile) GNUBuildID() (BuildID, error) { return BuildID{}, fmt.Errorf(".note.gnu.build-id is not a GNU build-id : %s", hex.EncodeToString(data)) } rawBuildID := data[16:] - if len(rawBuildID) != 20 && len(rawBuildID) != 8 { // 8 is xxhash, for example in Container-Optimized OS + if len(rawBuildID) < 8 { return BuildID{}, fmt.Errorf(".note.gnu.build-id has wrong size %s : %s ", f.fpath, hex.EncodeToString(data)) } buildIDHex := hex.EncodeToString(rawBuildID)