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 <vmalik@redhat.com>
This commit is contained in:
Viktor Malik 2023-03-14 08:17:08 +01:00
parent 73942f931b
commit 2fbe8b0169
No known key found for this signature in database
GPG Key ID: AF7A2E1F6EE74FB3
8 changed files with 274 additions and 636 deletions

1
.gitignore vendored
View File

@ -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

View File

@ -1,457 +0,0 @@
From 7afe3ced2b91d940a8d72755043ac2468687f1ee Mon Sep 17 00:00:00 2001
From: Viktor Malik <viktor.malik@gmail.com>
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<Value *> args,
const Twine &Name)
{
#if LLVM_VERSION_MAJOR >= 11
- auto *calleePtrType = cast<PointerType>(callee->getType());
- auto *calleeType = cast<FunctionType>(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<AllocaInst>(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<std::string> literal1;
- if (auto constString1 = dyn_cast<ConstantDataArray>(val1))
+ if (auto constString1 = dyn_cast<ConstantDataArray>(str1))
literal1 = constString1->getAsString();
- else if (isa<ConstantAggregateZero>(val1))
+ else if (isa<ConstantAggregateZero>(str1))
literal1 = "";
else
literal1 = std::nullopt;
std::optional<std::string> literal2;
- if (auto constString2 = dyn_cast<ConstantDataArray>(val2))
+ if (auto constString2 = dyn_cast<ConstantDataArray>(str2))
literal2 = constString2->getAsString();
- else if (isa<ConstantAggregateZero>(val2))
+ else if (isa<ConstantAggregateZero>(str2))
literal2 = "";
else
literal2 = std::nullopt;
- auto *val1p = dyn_cast<PointerType>(val1->getType());
- auto *val2p = dyn_cast<PointerType>(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<Value *> args,
const Twine &Name,
const location *loc = nullptr);
- CallInst *createCall(Value *callee, ArrayRef<Value *> args, const Twine &Name);
+ CallInst *createCall(FunctionType *callee_type,
+ Value *callee,
+ ArrayRef<Value *> 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<std::string, StructType *> 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<Variable &>(*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

View File

@ -1,174 +0,0 @@
From 652562eef0d53649cf29c256bc20abdffdd195ab Mon Sep 17 00:00:00 2001
From: Rong Tao <rongtao@cestc.cn>
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 <rongtao@cestc.cn>
---
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 <linux/socket.h>
+#include <net/sock.h>
+#else
+#include <sys/socket.h>
+#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

View File

@ -0,0 +1,160 @@
From 79d849a3a0462ab0a33cbf208e27e28d05eab213 Mon Sep 17 00:00:00 2001
From: Viktor Malik <viktor.malik@gmail.com>
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<libbpf::bpf_func_id, location> helper_use_loc_;
// mapping traceable functions to modules (or "vmlinux") that they appear in
FuncsModulesMap traceable_funcs_;
+ KConfig kconfig;
std::vector<std::unique_ptr<AttachedProbe>> attached_probes_;
std::map<std::string, std::unique_ptr<PCAPwriter>> 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 <bcc/bcc_syms.h>
#include <bcc/bcc_usdt.h>
#include <elf.h>
+#include <zlib.h>
#include <linux/version.h>
@@ -178,6 +179,55 @@ StdioSilencer::~StdioSilencer()
}
}
+KConfig::KConfig()
+{
+ std::vector<std::string> 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<std::string, std::unordered_set<std::string>>
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<std::string, std::string> config;
+};
+
static std::vector<DeprecatedName> 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

View File

@ -0,0 +1,103 @@
From 29c5d381cd4d36b5e3ce140193729a5a4b97c31e Mon Sep 17 00:00:00 2001
From: Viktor Malik <viktor.malik@gmail.com>
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<struct timespec> 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<int> get_possible_cpus()
return read_cpu_range("/sys/devices/system/cpu/possible");
}
-std::vector<std::string> get_kernel_cflags(
- const char* uname_machine,
- const std::string& ksrc,
- const std::string& kobj)
+std::vector<std::string> get_kernel_cflags(const char *uname_machine,
+ const std::string &ksrc,
+ const std::string &kobj,
+ const KConfig &kconfig)
{
std::vector<std::string> cflags;
std::string arch = uname_machine;
@@ -433,6 +432,20 @@ std::vector<std::string> 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<std::string, std::string> get_kernel_dirs(
bool unpack_kheaders);
std::vector<std::string> 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<std::pair<std::string, std::string>> get_cgroup_hierarchy_roots();
--
2.39.2

View File

@ -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 <vmalik@redhat.com> - 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 <vmalik@redhat.com> - 0.16.0-2
- Fix missing kprobe attachpoints for bio* tools (s390x, ppc64le)
- Rebuild for libbpf 1.0.0

View File

@ -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