From 2fbe8b0169798e61650e4cb6033dc55e117a0a2e Mon Sep 17 00:00:00 2001 From: Viktor Malik Date: Tue, 14 Mar 2023 08:17:08 +0100 Subject: [PATCH] Rebase bpftrace to 0.17.0 In addition, fix runqlat.bt, tcpdrop.bt, and undump.bt on aarch64. Resolves: RHEL-286 Resolves: rhbz#2170838 Signed-off-by: Viktor Malik --- .gitignore | 1 + ...t-rid-of-getPointerElementType-calls.patch | 457 ------------------ ...R-Error-attaching-probe-kprobe-tcp_d.patch | 174 ------- ...17.0-0001-Parse-kernel-configuration.patch | 160 ++++++ ...e-the-KASAN_SHADOW_SCALE_SHIFT-macro.patch | 103 ++++ ...arch64-fixes-statsnoop-and-opensnoop.patch | 0 bpftrace.spec | 13 +- sources | 2 +- 8 files changed, 274 insertions(+), 636 deletions(-) delete mode 100644 bpftrace-0.16.0-IR-builder-get-rid-of-getPointerElementType-calls.patch delete mode 100644 bpftrace-0.16.0-tcpdrop-Fix-ERROR-Error-attaching-probe-kprobe-tcp_d.patch create mode 100644 bpftrace-0.17.0-0001-Parse-kernel-configuration.patch create mode 100644 bpftrace-0.17.0-0002-arm64-define-the-KASAN_SHADOW_SCALE_SHIFT-macro.patch rename bpftrace-0.16.0-RHEL-aarch64-fixes-statsnoop-and-opensnoop.patch => bpftrace-0.17.0-RHEL-aarch64-fixes-statsnoop-and-opensnoop.patch (100%) diff --git a/.gitignore b/.gitignore index 9303427..9156da0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ /bpftrace-0.13.1.tar.gz /bpftrace-0.16.0.tar.gz /cereal-1.3.2.tar.gz +/bpftrace-0.17.0.tar.gz diff --git a/bpftrace-0.16.0-IR-builder-get-rid-of-getPointerElementType-calls.patch b/bpftrace-0.16.0-IR-builder-get-rid-of-getPointerElementType-calls.patch deleted file mode 100644 index 8c4c547..0000000 --- a/bpftrace-0.16.0-IR-builder-get-rid-of-getPointerElementType-calls.patch +++ /dev/null @@ -1,457 +0,0 @@ -From 7afe3ced2b91d940a8d72755043ac2468687f1ee Mon Sep 17 00:00:00 2001 -From: Viktor Malik -Date: Mon, 10 Oct 2022 14:26:38 +0200 -Subject: [PATCH] IR builder: get rid of getPointerElementType calls - -Usage of Value::getPointerElementType is deprecated and will be dropped -in LLVM 16 [1]. - -There are several places where we use this method: -- function (value) calls - the called function type is usually - available, so just pass it to createCall, the only exception is - CreateProbeReadStr which must have been refactored -- getting the type of alloca instruction - there is a dedicated - AllocaInst::getAllocatedType method that can be used instead -- strncmp - pass sizes of the strings to CreateStrncmp to be able to get - the correct string type (which is array of uint8) - -[1] https://llvm.org/docs/OpaquePointers.html ---- - src/ast/irbuilderbpf.cpp | 143 ++++++++++++-------------------- - src/ast/irbuilderbpf.h | 23 +++-- - src/ast/passes/codegen_llvm.cpp | 30 +++++-- - 3 files changed, 86 insertions(+), 110 deletions(-) - -diff --git a/src/ast/irbuilderbpf.cpp b/src/ast/irbuilderbpf.cpp -index d49883f7..4036b2df 100644 ---- a/src/ast/irbuilderbpf.cpp -+++ b/src/ast/irbuilderbpf.cpp -@@ -288,17 +288,16 @@ CallInst *IRBuilderBPF::CreateHelperCall(libbpf::bpf_func_id func_id, - Constant *helper_func = ConstantExpr::getCast(Instruction::IntToPtr, - getInt64(func_id), - helper_ptr_type); -- return createCall(helper_func, args, Name); -+ return createCall(helper_type, helper_func, args, Name); - } - --CallInst *IRBuilderBPF::createCall(Value *callee, -+CallInst *IRBuilderBPF::createCall(FunctionType *callee_type, -+ Value *callee, - ArrayRef args, - const Twine &Name) - { - #if LLVM_VERSION_MAJOR >= 11 -- auto *calleePtrType = cast(callee->getType()); -- auto *calleeType = cast(calleePtrType->getPointerElementType()); -- return CreateCall(calleeType, callee, args, Name); -+ return CreateCall(callee_type, callee, args, Name); - #else - return CreateCall(callee, args, Name); - #endif -@@ -307,7 +306,7 @@ CallInst *IRBuilderBPF::createCall(Value *callee, - CallInst *IRBuilderBPF::CreateBpfPseudoCallId(int mapid) - { - Function *pseudo_func = module_.getFunction("llvm.bpf.pseudo"); -- return createCall(pseudo_func, -+ return CreateCall(pseudo_func, - { getInt64(BPF_PSEUDO_MAP_FD), getInt64(mapid) }, - "pseudo"); - } -@@ -346,7 +345,8 @@ CallInst *IRBuilderBPF::createMapLookup(int mapid, Value *key) - Instruction::IntToPtr, - getInt64(libbpf::BPF_FUNC_map_lookup_elem), - lookup_func_ptr_type); -- return createCall(lookup_func, { map_ptr, key }, "lookup_elem"); -+ return createCall( -+ lookup_func_type, lookup_func, { map_ptr, key }, "lookup_elem"); - } - - CallInst *IRBuilderBPF::CreateGetJoinMap(Value *ctx, const location &loc) -@@ -397,8 +397,7 @@ Value *IRBuilderBPF::CreateMapLookupElem(Value *ctx, - CREATE_MEMCPY(value, call, type.GetSize(), 1); - else - { -- assert(value->getType()->isPointerTy() && -- (value->getType()->getPointerElementType() == getInt64Ty())); -+ assert(value->getAllocatedType() == getInt64Ty()); - // createMapLookup returns an u8* - auto *cast = CreatePointerCast(call, value->getType(), "cast"); - CreateStore(CreateLoad(getInt64Ty(), cast), value); -@@ -448,7 +447,8 @@ void IRBuilderBPF::CreateMapUpdateElem(Value *ctx, - Instruction::IntToPtr, - getInt64(libbpf::BPF_FUNC_map_update_elem), - update_func_ptr_type); -- CallInst *call = createCall(update_func, -+ CallInst *call = createCall(update_func_type, -+ update_func, - { map_ptr, key, val, flags }, - "update_elem"); - CreateHelperErrorCond(ctx, call, libbpf::BPF_FUNC_map_update_elem, loc); -@@ -472,7 +472,8 @@ void IRBuilderBPF::CreateMapDeleteElem(Value *ctx, - Instruction::IntToPtr, - getInt64(libbpf::BPF_FUNC_map_delete_elem), - delete_func_ptr_type); -- CallInst *call = createCall(delete_func, { map_ptr, key }, "delete_elem"); -+ CallInst *call = createCall( -+ delete_func_type, delete_func, { map_ptr, key }, "delete_elem"); - CreateHelperErrorCond(ctx, call, libbpf::BPF_FUNC_map_delete_elem, loc); - } - -@@ -508,72 +509,53 @@ void IRBuilderBPF::CreateProbeRead(Value *ctx, - Constant *proberead_func = ConstantExpr::getCast(Instruction::IntToPtr, - getInt64(read_fn), - proberead_func_ptr_type); -- CallInst *call = createCall(proberead_func, -+ CallInst *call = createCall(proberead_func_type, -+ proberead_func, - { dst, size, src }, - probeReadHelperName(read_fn)); - CreateHelperErrorCond(ctx, call, read_fn, loc); - } - --Constant *IRBuilderBPF::createProbeReadStrFn(llvm::Type *dst, -- llvm::Type *src, -- AddrSpace as) --{ -- assert(src && (src->isIntegerTy() || src->isPointerTy())); -- // int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr) -- FunctionType *probereadstr_func_type = FunctionType::get( -- getInt64Ty(), { dst, getInt32Ty(), src }, false); -- PointerType *probereadstr_func_ptr_type = PointerType::get( -- probereadstr_func_type, 0); -- return ConstantExpr::getCast(Instruction::IntToPtr, -- getInt64(selectProbeReadHelper(as, true)), -- probereadstr_func_ptr_type); --} -- - CallInst *IRBuilderBPF::CreateProbeReadStr(Value *ctx, -- AllocaInst *dst, -+ Value *dst, - size_t size, - Value *src, - AddrSpace as, - const location &loc) - { -- assert(ctx && ctx->getType() == getInt8PtrTy()); - return CreateProbeReadStr(ctx, dst, getInt32(size), src, as, loc); - } - - CallInst *IRBuilderBPF::CreateProbeReadStr(Value *ctx, - Value *dst, -- size_t size, -- Value *src, -- AddrSpace as, -- const location &loc) --{ -- assert(ctx && ctx->getType() == getInt8PtrTy()); -- Constant *fn = createProbeReadStrFn(dst->getType(), src->getType(), as); -- auto read_fn = selectProbeReadHelper(as, true); -- CallInst *call = createCall(fn, -- { dst, getInt32(size), src }, -- probeReadHelperName(read_fn)); -- CreateHelperErrorCond(ctx, call, read_fn, loc); -- return call; --} -- --CallInst *IRBuilderBPF::CreateProbeReadStr(Value *ctx, -- AllocaInst *dst, - llvm::Value *size, - Value *src, - AddrSpace as, - const location &loc) - { - assert(ctx && ctx->getType() == getInt8PtrTy()); -- assert(dst && dst->getAllocatedType()->isArrayTy() && -- dst->getAllocatedType()->getArrayElementType() == getInt8Ty()); - assert(size && size->getType()->isIntegerTy()); -+ if (auto *dst_alloca = dyn_cast(dst)) -+ { -+ assert(dst_alloca->getAllocatedType()->isArrayTy() && -+ dst_alloca->getAllocatedType()->getArrayElementType() == -+ getInt8Ty()); -+ } - -- auto *size_i32 = CreateIntCast(size, getInt32Ty(), false); -+ auto *size_i32 = size; -+ if (size_i32->getType()->getScalarSizeInBits() != 32) -+ size_i32 = CreateIntCast(size_i32, getInt32Ty(), false); - -- Constant *fn = createProbeReadStrFn(dst->getType(), src->getType(), as); - auto read_fn = selectProbeReadHelper(as, true); -- CallInst *call = createCall(fn, -+ // int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr) -+ FunctionType *probereadstr_func_type = FunctionType::get( -+ getInt64Ty(), { dst->getType(), getInt32Ty(), src->getType() }, false); -+ PointerType *probereadstr_func_ptr_type = PointerType::get( -+ probereadstr_func_type, 0); -+ Constant *probereadstr_callee = ConstantExpr::getCast( -+ Instruction::IntToPtr, getInt64(read_fn), probereadstr_func_ptr_type); -+ CallInst *call = createCall(probereadstr_func_type, -+ probereadstr_callee, - { dst, size_i32, src }, - probeReadHelperName(read_fn)); - CreateHelperErrorCond(ctx, call, read_fn, loc); -@@ -732,8 +714,10 @@ Value *IRBuilderBPF::CreateUSDTReadArgument(Value *ctx, - return result; - } - --Value *IRBuilderBPF::CreateStrncmp(Value *val1, -- Value *val2, -+Value *IRBuilderBPF::CreateStrncmp(Value *str1, -+ uint64_t str1_size, -+ Value *str2, -+ uint64_t str2_size, - uint64_t n, - bool inverse) - { -@@ -762,40 +746,21 @@ Value *IRBuilderBPF::CreateStrncmp(Value *val1, - // Check if the compared strings are literals. - // If so, we can avoid storing the literal in memory. - std::optional literal1; -- if (auto constString1 = dyn_cast(val1)) -+ if (auto constString1 = dyn_cast(str1)) - literal1 = constString1->getAsString(); -- else if (isa(val1)) -+ else if (isa(str1)) - literal1 = ""; - else - literal1 = std::nullopt; - - std::optional literal2; -- if (auto constString2 = dyn_cast(val2)) -+ if (auto constString2 = dyn_cast(str2)) - literal2 = constString2->getAsString(); -- else if (isa(val2)) -+ else if (isa(str2)) - literal2 = ""; - else - literal2 = std::nullopt; - -- auto *val1p = dyn_cast(val1->getType()); -- auto *val2p = dyn_cast(val2->getType()); --#ifndef NDEBUG -- if (!literal1) -- { -- assert(val1p); -- assert(val1p->getPointerElementType()->isArrayTy() && -- val1p->getPointerElementType()->getArrayElementType() == -- getInt8Ty()); -- } -- if (!literal2) -- { -- assert(val2p); -- assert(val2p->getPointerElementType()->isArrayTy() && -- val2p->getPointerElementType()->getArrayElementType() == -- getInt8Ty()); -- } --#endif -- - Function *parent = GetInsertBlock()->getParent(); - AllocaInst *store = CreateAllocaBPF(getInt1Ty(), "strcmp.result"); - BasicBlock *str_ne = BasicBlock::Create(module_.getContext(), -@@ -822,8 +787,8 @@ Value *IRBuilderBPF::CreateStrncmp(Value *val1, - l = getInt8(literal1->c_str()[i]); - else - { -- auto *ptr_l = CreateGEP(val1p->getPointerElementType(), -- val1, -+ auto *ptr_l = CreateGEP(ArrayType::get(getInt8Ty(), str1_size), -+ str1, - { getInt32(0), getInt32(i) }); - l = CreateLoad(getInt8Ty(), ptr_l); - } -@@ -833,8 +798,8 @@ Value *IRBuilderBPF::CreateStrncmp(Value *val1, - r = getInt8(literal2->c_str()[i]); - else - { -- auto *ptr_r = CreateGEP(val2p->getPointerElementType(), -- val2, -+ auto *ptr_r = CreateGEP(ArrayType::get(getInt8Ty(), str2_size), -+ str2, - { getInt32(0), getInt32(i) }); - r = CreateLoad(getInt8Ty(), ptr_r); - } -@@ -994,11 +959,9 @@ void IRBuilderBPF::CreateGetCurrentComm(Value *ctx, - size_t size, - const location &loc) - { -- assert(buf->getType()->getPointerElementType()->isArrayTy() && -- buf->getType()->getPointerElementType()->getArrayNumElements() >= -- size && -- buf->getType()->getPointerElementType()->getArrayElementType() == -- getInt8Ty()); -+ assert(buf->getAllocatedType()->isArrayTy() && -+ buf->getAllocatedType()->getArrayNumElements() >= size && -+ buf->getAllocatedType()->getArrayElementType() == getInt8Ty()); - - // long bpf_get_current_comm(char *buf, int size_of_buf) - // Return: 0 on success or negative error -@@ -1077,7 +1040,7 @@ void IRBuilderBPF::CreateSignal(Value *ctx, Value *sig, const location &loc) - Instruction::IntToPtr, - getInt64(libbpf::BPF_FUNC_send_signal), - signal_func_ptr_type); -- CallInst *call = createCall(signal_func, { sig }, "signal"); -+ CallInst *call = createCall(signal_func_type, signal_func, { sig }, "signal"); - CreateHelperErrorCond(ctx, call, libbpf::BPF_FUNC_send_signal, loc); - } - -@@ -1091,7 +1054,7 @@ void IRBuilderBPF::CreateOverrideReturn(Value *ctx, Value *rc) - Constant *override_func = ConstantExpr::getCast(Instruction::IntToPtr, - getInt64(libbpf::BPF_FUNC_override_return), - override_func_ptr_type); -- createCall(override_func, { ctx, rc }, "override"); -+ createCall(override_func_type, override_func, { ctx, rc }, "override"); - } - - CallInst *IRBuilderBPF::CreateSkbOutput(Value *skb, -@@ -1126,7 +1089,8 @@ CallInst *IRBuilderBPF::CreateSkbOutput(Value *skb, - Instruction::IntToPtr, - getInt64(libbpf::BPF_FUNC_skb_output), - skb_output_func_ptr_type); -- CallInst *call = createCall(skb_output_func, -+ CallInst *call = createCall(skb_output_func_type, -+ skb_output_func, - { skb, map_ptr, flags, data, size_val }, - "skb_output"); - return call; -@@ -1320,7 +1284,8 @@ void IRBuilderBPF::CreateSeqPrintf(Value *ctx, - CreateGEP(getInt64Ty(), meta, getInt64(0)), - "seq"); - -- CallInst *call = createCall(seq_printf_func, -+ CallInst *call = createCall(seq_printf_func_type, -+ seq_printf_func, - { seq, fmt, fmt_size, data, data_len }, - "seq_printf"); - CreateHelperErrorCond(ctx, call, libbpf::BPF_FUNC_seq_printf, loc); -diff --git a/src/ast/irbuilderbpf.h b/src/ast/irbuilderbpf.h -index e124911b..c9ffb545 100644 ---- a/src/ast/irbuilderbpf.h -+++ b/src/ast/irbuilderbpf.h -@@ -90,17 +90,11 @@ public: - AddrSpace as, - const location &loc); - CallInst *CreateProbeReadStr(Value *ctx, -- AllocaInst *dst, -+ Value *dst, - llvm::Value *size, - Value *src, - AddrSpace as, - const location &loc); -- CallInst *CreateProbeReadStr(Value *ctx, -- AllocaInst *dst, -- size_t size, -- Value *src, -- AddrSpace as, -- const location &loc); - CallInst *CreateProbeReadStr(Value *ctx, - Value *dst, - size_t size, -@@ -115,7 +109,12 @@ public: - pid_t pid, - AddrSpace as, - const location &loc); -- Value *CreateStrncmp(Value *val1, Value *val2, uint64_t n, bool inverse); -+ Value *CreateStrncmp(Value *str1, -+ uint64_t str1_size, -+ Value *str2, -+ uint64_t str2_size, -+ uint64_t n, -+ bool inverse); - CallInst *CreateGetNs(bool boot_time, const location &loc); - CallInst *CreateGetPidTgid(const location &loc); - CallInst *CreateGetCurrentCgroupId(const location &loc); -@@ -131,7 +130,10 @@ public: - ArrayRef args, - const Twine &Name, - const location *loc = nullptr); -- CallInst *createCall(Value *callee, ArrayRef args, const Twine &Name); -+ CallInst *createCall(FunctionType *callee_type, -+ Value *callee, -+ ArrayRef args, -+ const Twine &Name); - void CreateGetCurrentComm(Value *ctx, AllocaInst *buf, size_t size, const location& loc); - void CreatePerfEventOutput(Value *ctx, - Value *data, -@@ -185,9 +187,6 @@ private: - AddrSpace as, - const location &loc); - CallInst *createMapLookup(int mapid, Value *key); -- Constant *createProbeReadStrFn(llvm::Type *dst, -- llvm::Type *src, -- AddrSpace as); - libbpf::bpf_func_id selectProbeReadHelper(AddrSpace as, bool str); - - std::map structs_; -diff --git a/src/ast/passes/codegen_llvm.cpp b/src/ast/passes/codegen_llvm.cpp -index a818ca0b..2b888087 100644 ---- a/src/ast/passes/codegen_llvm.cpp -+++ b/src/ast/passes/codegen_llvm.cpp -@@ -1133,8 +1133,12 @@ void CodegenLLVM::visit(Call &call) - auto left_string = getString(left_arg); - auto right_string = getString(right_arg); - -- expr_ = b_.CreateStrncmp( -- left_string.first, right_string.first, size, false); -+ expr_ = b_.CreateStrncmp(left_string.first, -+ left_string.second, -+ right_string.first, -+ right_string.second, -+ size, -+ false); - } - else if (call.func == "override") - { -@@ -1269,8 +1273,7 @@ void CodegenLLVM::visit(Variable &var) - else - { - auto *var_alloca = variables_[var.ident]; -- expr_ = b_.CreateLoad(var_alloca->getType()->getPointerElementType(), -- var_alloca); -+ expr_ = b_.CreateLoad(var_alloca->getAllocatedType(), var_alloca); - } - } - -@@ -1310,7 +1313,12 @@ void CodegenLLVM::binop_string(Binop &binop) - auto right_string = getString(binop.right); - - size_t len = std::min(left_string.second, right_string.second); -- expr_ = b_.CreateStrncmp(left_string.first, right_string.first, len, inverse); -+ expr_ = b_.CreateStrncmp(left_string.first, -+ left_string.second, -+ right_string.first, -+ right_string.second, -+ len, -+ inverse); - } - - void CodegenLLVM::binop_buf(Binop &binop) -@@ -1334,7 +1342,12 @@ void CodegenLLVM::binop_buf(Binop &binop) - - size_t len = std::min(binop.left->type.GetSize(), - binop.right->type.GetSize()); -- expr_ = b_.CreateStrncmp(left_string, right_string, len, inverse); -+ expr_ = b_.CreateStrncmp(left_string, -+ binop.left->type.GetSize(), -+ right_string, -+ binop.right->type.GetSize(), -+ len, -+ inverse); - } - - void CodegenLLVM::binop_int(Binop &binop) -@@ -3528,9 +3541,8 @@ void CodegenLLVM::createIncDec(Unop &unop) - else if (unop.expr->is_variable) - { - Variable &var = static_cast(*unop.expr); -- Value *oldval = b_.CreateLoad( -- variables_[var.ident]->getType()->getPointerElementType(), -- variables_[var.ident]); -+ Value *oldval = b_.CreateLoad(variables_[var.ident]->getAllocatedType(), -+ variables_[var.ident]); - Value *newval; - if (is_increment) - newval = b_.CreateAdd(oldval, b_.GetIntSameSize(step, oldval)); --- -2.38.1 - diff --git a/bpftrace-0.16.0-tcpdrop-Fix-ERROR-Error-attaching-probe-kprobe-tcp_d.patch b/bpftrace-0.16.0-tcpdrop-Fix-ERROR-Error-attaching-probe-kprobe-tcp_d.patch deleted file mode 100644 index 2e013e6..0000000 --- a/bpftrace-0.16.0-tcpdrop-Fix-ERROR-Error-attaching-probe-kprobe-tcp_d.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 652562eef0d53649cf29c256bc20abdffdd195ab Mon Sep 17 00:00:00 2001 -From: Rong Tao -Date: Sat, 1 Oct 2022 16:15:27 +0800 -Subject: [PATCH 1/2] tcpdrop: Fix: ERROR: Error attaching probe: - 'kprobe:tcp_drop' - -kernel commit 8fbf195798b5('tcp_drop() is no longer needed.') remove -the kprobe:tcp_drop, bcc commit 16eab39171eb('Add -tracepoint:skb:kfree_skb if no tcp_drop() kprobe.') already fix this -problem. - -CI old kernel is too old and not support the 'reason' field, move the -old tools/tcpdrop.bt into tools/old/tcpdrop.bt and set the CI to use -it. - -Since 5.17 support trace_kfree_skb(skb, ..., reason) 'reason' field. -Since 5.19 remove tcp_drop() function. - -ERROR log: - - $ sudo ./tcpdrop.bt - ./tcpdrop.bt:49-51: WARNING: tcp_drop is not traceable (either non-existing, inlined, or marked as "notrace"); attaching to it will likely fail - Attaching 3 probes... - cannot attach kprobe, probe entry may not exist - ERROR: Error attaching probe: 'kprobe:tcp_drop' - -Link: https://github.com/iovisor/bpftrace/pull/2379 -Signed-off-by: Rong Tao ---- - tools/old/tcpdrop.bt | 85 ++++++++++++++++++++++++++++++++++++++++++++ - tools/tcpdrop.bt | 22 ++++++------ - 2 files changed, 97 insertions(+), 10 deletions(-) - create mode 100755 tools/old/tcpdrop.bt - -diff --git a/tools/old/tcpdrop.bt b/tools/old/tcpdrop.bt -new file mode 100755 -index 00000000..685a5f6a ---- /dev/null -+++ b/tools/old/tcpdrop.bt -@@ -0,0 +1,85 @@ -+#!/usr/bin/env bpftrace -+/* -+ * tcpdrop.bt Trace TCP kernel-dropped packets/segments. -+ * For Linux, uses bpftrace and eBPF. -+ * -+ * USAGE: tcpdrop.bt -+ * -+ * This is a bpftrace version of the bcc tool of the same name. -+ * It is limited to ipv4 addresses, and cannot show tcp flags. -+ * -+ * This provides information such as packet details, socket state, and kernel -+ * stack trace for packets/segments that were dropped via tcp_drop(). -+ -+ * WARNING: this script attaches to the tcp_drop kprobe which is likely inlined -+ * on newer kernels and not replaced by anything else, therefore -+ * the script will stop working -+ * -+ * For Linux <= 5.18. -+ * -+ * Copyright (c) 2018 Dale Hamel. -+ * Licensed under the Apache License, Version 2.0 (the "License") -+ * -+ * 23-Nov-2018 Dale Hamel created this. -+ */ -+ -+#ifndef BPFTRACE_HAVE_BTF -+#include -+#include -+#else -+#include -+#endif -+ -+BEGIN -+{ -+ printf("Tracing tcp drops. Hit Ctrl-C to end.\n"); -+ printf("%-8s %-8s %-16s %-21s %-21s %-8s\n", "TIME", "PID", "COMM", "SADDR:SPORT", "DADDR:DPORT", "STATE"); -+ -+ // See https://github.com/torvalds/linux/blob/master/include/net/tcp_states.h -+ @tcp_states[1] = "ESTABLISHED"; -+ @tcp_states[2] = "SYN_SENT"; -+ @tcp_states[3] = "SYN_RECV"; -+ @tcp_states[4] = "FIN_WAIT1"; -+ @tcp_states[5] = "FIN_WAIT2"; -+ @tcp_states[6] = "TIME_WAIT"; -+ @tcp_states[7] = "CLOSE"; -+ @tcp_states[8] = "CLOSE_WAIT"; -+ @tcp_states[9] = "LAST_ACK"; -+ @tcp_states[10] = "LISTEN"; -+ @tcp_states[11] = "CLOSING"; -+ @tcp_states[12] = "NEW_SYN_RECV"; -+} -+ -+kprobe:tcp_drop -+{ -+ $sk = ((struct sock *) arg0); -+ $inet_family = $sk->__sk_common.skc_family; -+ -+ if ($inet_family == AF_INET || $inet_family == AF_INET6) { -+ if ($inet_family == AF_INET) { -+ $daddr = ntop($sk->__sk_common.skc_daddr); -+ $saddr = ntop($sk->__sk_common.skc_rcv_saddr); -+ } else { -+ $daddr = ntop($sk->__sk_common.skc_v6_daddr.in6_u.u6_addr8); -+ $saddr = ntop($sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr8); -+ } -+ $lport = $sk->__sk_common.skc_num; -+ $dport = $sk->__sk_common.skc_dport; -+ -+ // Destination port is big endian, it must be flipped -+ $dport = bswap($dport); -+ -+ $state = $sk->__sk_common.skc_state; -+ $statestr = @tcp_states[$state]; -+ -+ time("%H:%M:%S "); -+ printf("%-8d %-16s ", pid, comm); -+ printf("%39s:%-6d %39s:%-6d %-10s\n", $saddr, $lport, $daddr, $dport, $statestr); -+ printf("%s\n", kstack); -+ } -+} -+ -+END -+{ -+ clear(@tcp_states); -+} -diff --git a/tools/tcpdrop.bt b/tools/tcpdrop.bt -index 3450a533..bb31107f 100755 ---- a/tools/tcpdrop.bt -+++ b/tools/tcpdrop.bt -@@ -9,16 +9,15 @@ - * It is limited to ipv4 addresses, and cannot show tcp flags. - * - * This provides information such as packet details, socket state, and kernel -- * stack trace for packets/segments that were dropped via tcp_drop(). -- -- * WARNING: this script attaches to the tcp_drop kprobe which is likely inlined -- * on newer kernels and not replaced by anything else, therefore -- * the script will stop working -- -+ * stack trace for packets/segments that were dropped via kfree_skb. -+ * -+ * For Linux 5.17+ (see tools/old for script for lower versions). -+ * - * Copyright (c) 2018 Dale Hamel. - * Licensed under the Apache License, Version 2.0 (the "License") -- -+ * - * 23-Nov-2018 Dale Hamel created this. -+ * 01-Oct-2022 Rong Tao use tracepoint:skb:kfree_skb - */ - - #ifndef BPFTRACE_HAVE_BTF -@@ -48,12 +47,15 @@ BEGIN - @tcp_states[12] = "NEW_SYN_RECV"; - } - --kprobe:tcp_drop -+tracepoint:skb:kfree_skb - { -- $sk = ((struct sock *) arg0); -+ $reason = args->reason; -+ $skb = (struct sk_buff *)args->skbaddr; -+ $sk = ((struct sock *) $skb->sk); - $inet_family = $sk->__sk_common.skc_family; - -- if ($inet_family == AF_INET || $inet_family == AF_INET6) { -+ if ($reason > SKB_DROP_REASON_NOT_SPECIFIED && -+ ($inet_family == AF_INET || $inet_family == AF_INET6)) { - if ($inet_family == AF_INET) { - $daddr = ntop($sk->__sk_common.skc_daddr); - $saddr = ntop($sk->__sk_common.skc_rcv_saddr); --- -2.38.1 - diff --git a/bpftrace-0.17.0-0001-Parse-kernel-configuration.patch b/bpftrace-0.17.0-0001-Parse-kernel-configuration.patch new file mode 100644 index 0000000..819810c --- /dev/null +++ b/bpftrace-0.17.0-0001-Parse-kernel-configuration.patch @@ -0,0 +1,160 @@ +From 79d849a3a0462ab0a33cbf208e27e28d05eab213 Mon Sep 17 00:00:00 2001 +From: Viktor Malik +Date: Fri, 3 Mar 2023 08:28:54 +0100 +Subject: [PATCH 1/2] Parse kernel configuration + +In future, it may (and will) be useful to have access to the running +kernel configuration, e.g. to add config-specific compilation options to +ClangParser. + +This adds and fills a new map BPFtrace::kconfig that maps config options +to their values. Both the option name and the value are strings. The +configuration is parsed from one of two sources: +- /boot/config-$(uname -r) +- /proc/config.gz + +For testing purposes, the config filename may be passed through the +BPFTRACE_KCONFIG_TEST env variable. +--- + src/bpftrace.h | 1 + + src/utils.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ + src/utils.h | 12 ++++++++++++ + tests/utils.cpp | 19 +++++++++++++++++++ + 4 files changed, 82 insertions(+) + +diff --git a/src/bpftrace.h b/src/bpftrace.h +index a6a8c00b..94587bff 100644 +--- a/src/bpftrace.h ++++ b/src/bpftrace.h +@@ -168,6 +168,7 @@ public: + std::map helper_use_loc_; + // mapping traceable functions to modules (or "vmlinux") that they appear in + FuncsModulesMap traceable_funcs_; ++ KConfig kconfig; + std::vector> attached_probes_; + + std::map> pcap_writers; +diff --git a/src/utils.cpp b/src/utils.cpp +index 2d9c6695..54c8f054 100644 +--- a/src/utils.cpp ++++ b/src/utils.cpp +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include + +@@ -178,6 +179,55 @@ StdioSilencer::~StdioSilencer() + } + } + ++KConfig::KConfig() ++{ ++ std::vector config_locs; ++ ++ // Try to get the config from BPFTRACE_KCONFIG_TEST env ++ // If not set, use the set of default locations ++ const char *path_env = std::getenv("BPFTRACE_KCONFIG_TEST"); ++ if (path_env) ++ config_locs = { std::string(path_env) }; ++ else ++ { ++ struct utsname utsname; ++ if (uname(&utsname) < 0) ++ return; ++ config_locs = { ++ "/boot/config-" + std::string(utsname.release), ++ "/proc/config.gz", ++ }; ++ } ++ ++ for (auto &path : config_locs) ++ { ++ // gzopen/gzgets handle both uncompressed and compressed files ++ gzFile file = gzopen(path.c_str(), "r"); ++ if (!file) ++ continue; ++ ++ char buf[4096]; ++ while (gzgets(file, buf, sizeof(buf))) ++ { ++ std::string option(buf); ++ if (option.find("CONFIG_") == 0) ++ { ++ // trim trailing '\n' ++ if (option[option.length() - 1] == '\n') ++ option = option.substr(0, option.length() - 1); ++ ++ auto split = option.find("="); ++ if (split == std::string::npos) ++ continue; ++ ++ config.emplace(option.substr(0, split), option.substr(split + 1)); ++ } ++ } ++ gzclose(file); ++ } ++} ++ ++ + bool get_uint64_env_var(const std::string &str, uint64_t &dest) + { + if (const char* env_p = std::getenv(str.c_str())) +diff --git a/src/utils.h b/src/utils.h +index dccc4504..a76aa161 100644 +--- a/src/utils.h ++++ b/src/utils.h +@@ -130,6 +130,18 @@ struct DeprecatedName + typedef std::unordered_map> + FuncsModulesMap; + ++struct KConfig ++{ ++ KConfig(); ++ bool has_value(const std::string &name, const std::string &value) const ++ { ++ auto c = config.find(name); ++ return c != config.end() && c->second == value; ++ } ++ ++ std::unordered_map config; ++}; ++ + static std::vector DEPRECATED_LIST = + { + }; +diff --git a/tests/utils.cpp b/tests/utils.cpp +index 9ca4ace5..8470745b 100644 +--- a/tests/utils.cpp ++++ b/tests/utils.cpp +@@ -222,6 +222,25 @@ TEST(utils, get_cgroup_path_in_hierarchy) + } + } + ++TEST(utils, parse_kconfig) ++{ ++ char path[] = "/tmp/configXXXXXX"; ++ int fd = mkstemp(path); ++ const std::string config = "# Intro comment\n" ++ "CONFIG_YES=y\n" ++ "CONFIG_MOD=m\n" ++ "CONFIG_VAL=42\n" ++ "# CONFIG_NO is not set"; ++ EXPECT_EQ(write(fd, config.c_str(), config.length()), config.length()); ++ setenv("BPFTRACE_KCONFIG_TEST", path, true); ++ ++ KConfig kconfig; ++ ASSERT_TRUE(kconfig.has_value("CONFIG_YES", "y")); ++ ASSERT_TRUE(kconfig.has_value("CONFIG_MOD", "m")); ++ ASSERT_TRUE(kconfig.has_value("CONFIG_VAL", "42")); ++ ASSERT_EQ(kconfig.config.find("CONFIG_NO"), kconfig.config.end()); ++} ++ + } // namespace utils + } // namespace test + } // namespace bpftrace +-- +2.39.2 + diff --git a/bpftrace-0.17.0-0002-arm64-define-the-KASAN_SHADOW_SCALE_SHIFT-macro.patch b/bpftrace-0.17.0-0002-arm64-define-the-KASAN_SHADOW_SCALE_SHIFT-macro.patch new file mode 100644 index 0000000..fe837a1 --- /dev/null +++ b/bpftrace-0.17.0-0002-arm64-define-the-KASAN_SHADOW_SCALE_SHIFT-macro.patch @@ -0,0 +1,103 @@ +From 29c5d381cd4d36b5e3ce140193729a5a4b97c31e Mon Sep 17 00:00:00 2001 +From: Viktor Malik +Date: Mon, 6 Mar 2023 11:41:27 +0100 +Subject: [PATCH 2/2] arm64: define the KASAN_SHADOW_SCALE_SHIFT macro + +arm64 defines this macro from Makefile instead of defining it in a +header file as is the case for other architectures. Since we're not +running make, we need to define the macro manually via CFLAGS. + +The value definition is taken from kernel's arch/arm64/Makefile and it +depends on the running kernel configuration. + +This fixes the runqlat.bt tcpdrop.bt, and undump.bt tools on +aarch64+debug kernel which previously failed with: + + # /usr/share/bpftrace/tools/runqlat.bt + [...]/source/arch/arm64/include/asm/memory.h:300:9: error: use of undeclared identifier 'KASAN_SHADOW_SCALE_SHIFT' + [...] +--- + src/main.cpp | 3 ++- + src/utils.cpp | 23 ++++++++++++++++++----- + src/utils.h | 3 ++- + 3 files changed, 22 insertions(+), 7 deletions(-) + +diff --git a/src/main.cpp b/src/main.cpp +index b76d1bb3..593c71be 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -370,7 +370,8 @@ static std::optional get_boottime() + kobj = std::get<1>(kdirs); + + if (ksrc != "") +- extra_flags = get_kernel_cflags(utsname.machine, ksrc, kobj); ++ extra_flags = get_kernel_cflags( ++ utsname.machine, ksrc, kobj, bpftrace.kconfig); + } + extra_flags.push_back("-include"); + extra_flags.push_back(CLANG_WORKAROUNDS_H); +diff --git a/src/utils.cpp b/src/utils.cpp +index 54c8f054..c8fd7da1 100644 +--- a/src/utils.cpp ++++ b/src/utils.cpp +@@ -227,7 +227,6 @@ KConfig::KConfig() + } + } + +- + bool get_uint64_env_var(const std::string &str, uint64_t &dest) + { + if (const char* env_p = std::getenv(str.c_str())) +@@ -364,10 +363,10 @@ std::vector get_possible_cpus() + return read_cpu_range("/sys/devices/system/cpu/possible"); + } + +-std::vector get_kernel_cflags( +- const char* uname_machine, +- const std::string& ksrc, +- const std::string& kobj) ++std::vector get_kernel_cflags(const char *uname_machine, ++ const std::string &ksrc, ++ const std::string &kobj, ++ const KConfig &kconfig) + { + std::vector cflags; + std::string arch = uname_machine; +@@ -433,6 +432,20 @@ std::vector get_kernel_cflags( + cflags.push_back("-D__LINUX_ARM_ARCH__=7"); + } + ++ if (arch == "arm64") ++ { ++ // arm64 defines KASAN_SHADOW_SCALE_SHIFT in a Makefile instead of defining ++ // it in a header file. Since we're not executing make, we need to set the ++ // value manually (values are taken from arch/arm64/Makefile). ++ if (kconfig.has_value("CONFIG_KASAN", "y")) ++ { ++ if (kconfig.has_value("CONFIG_KASAN_SW_TAGS", "y")) ++ cflags.push_back("-DKASAN_SHADOW_SCALE_SHIFT=4"); ++ else ++ cflags.push_back("-DKASAN_SHADOW_SCALE_SHIFT=3"); ++ } ++ } ++ + return cflags; + } + +diff --git a/src/utils.h b/src/utils.h +index a76aa161..d4eeac3d 100644 +--- a/src/utils.h ++++ b/src/utils.h +@@ -178,7 +178,8 @@ std::tuple get_kernel_dirs( + bool unpack_kheaders); + std::vector get_kernel_cflags(const char *uname_machine, + const std::string &ksrc, +- const std::string &kobj); ++ const std::string &kobj, ++ const KConfig &kconfig); + std::string get_cgroup_path_in_hierarchy(uint64_t cgroupid, + std::string base_path); + std::vector> get_cgroup_hierarchy_roots(); +-- +2.39.2 + diff --git a/bpftrace-0.16.0-RHEL-aarch64-fixes-statsnoop-and-opensnoop.patch b/bpftrace-0.17.0-RHEL-aarch64-fixes-statsnoop-and-opensnoop.patch similarity index 100% rename from bpftrace-0.16.0-RHEL-aarch64-fixes-statsnoop-and-opensnoop.patch rename to bpftrace-0.17.0-RHEL-aarch64-fixes-statsnoop-and-opensnoop.patch diff --git a/bpftrace.spec b/bpftrace.spec index bffdf5a..499408e 100644 --- a/bpftrace.spec +++ b/bpftrace.spec @@ -1,6 +1,6 @@ Name: bpftrace -Version: 0.16.0 -Release: 2%{?dist} +Version: 0.17.0 +Release: 1%{?dist} Summary: High-level tracing language for Linux eBPF License: ASL 2.0 @@ -13,8 +13,8 @@ Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz # for build. Source1: https://github.com/USCiLab/cereal/archive/v%{cereal_version}/cereal-%{cereal_version}.tar.gz -Patch0: %{name}-%{version}-IR-builder-get-rid-of-getPointerElementType-calls.patch -Patch1: %{name}-%{version}-tcpdrop-Fix-ERROR-Error-attaching-probe-kprobe-tcp_d.patch +Patch0: %{name}-%{version}-0001-Parse-kernel-configuration.patch +Patch1: %{name}-%{version}-0002-arm64-define-the-KASAN_SHADOW_SCALE_SHIFT-macro.patch Patch10: %{name}-%{version}-RHEL-aarch64-fixes-statsnoop-and-opensnoop.patch @@ -60,6 +60,7 @@ CPATH=$PWD/cereal-%{cereal_version}/include:$CPATH export CPATH %cmake . \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DUSE_SYSTEM_BPF_BCC=ON \ -DBUILD_TESTING:BOOL=OFF \ -DBUILD_SHARED_LIBS:BOOL=OFF %cmake_build @@ -95,6 +96,10 @@ find %{buildroot}%{_datadir}/%{name}/tools -type f -exec \ %exclude %{_datadir}/%{name}/tools/old %changelog +* Tue Mar 14 2023 Viktor Malik - 0.17.0-1 +- Rebase on bpftrace 0.17.0 (RHEL-286) +- Fix runqlat.bt, tcpdrop.bt, and undump.bt on aarch64 (rhbz#2170838) + * Tue Jan 03 2023 Viktor Malik - 0.16.0-2 - Fix missing kprobe attachpoints for bio* tools (s390x, ppc64le) - Rebuild for libbpf 1.0.0 diff --git a/sources b/sources index 9ba083d..216414c 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (bpftrace-0.16.0.tar.gz) = 52ca4fea4e2f8d2cbf0f9f1bc69af0ee3408201f019006dd2e838b9458cfc01761eba3df24c39e05cf93220d85d0cecc69bb44ec72f9f44cec0eb94479bff734 +SHA512 (bpftrace-0.17.0.tar.gz) = c3f17778ce4c42c2b6bc63245cd157e9fbc0b3f010b9f5b1284b691fbac47fbb532f3bd61d7e6fe525291e0034d62b3e8c1be6b8bf12cf26d5a39b5ab00a0d13 SHA512 (cereal-1.3.2.tar.gz) = 98d306d6292789129675f1c5c5aedcb90cfcc1029c4482893a8f9b23f3c9755e5ed4762d7a528f215345cae6392e87cd8d89467115b6f031b41c8673d6b4b109