From patchwork Tue Aug 20 10:23:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduard Zingerman X-Patchwork-Id: 13769857 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-pj1-f53.google.com (mail-pj1-f53.google.com [209.85.216.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CB7A718E757 for ; Tue, 20 Aug 2024 10:24:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149455; cv=none; b=JCWumbk8cmAPmGku3wF4xGWPOBErdWQZHJd1DBjwQ+68zL+J+1RZV7nMDSPySSSmBWxMX4AYObbT7MQinwknvfF7mepp4s6/L09Odu10I26/bFh7fU8iTrulpqDBWOHmeFjiEhpdA7wg+xDEL6u+LA0HrnMfF0KkmXco9ZB1oxQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149455; c=relaxed/simple; bh=kkYykJQL9R/aZ19ho2YF1MNC9bP/lNQhK5xnq9vtxUY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iJa9LF3NUcDq2MRpgF/YprlsBRNh1PpHXAi2mccj6YlfpVmzQHPDtp2asucVZ1Nb7scjKFSJndAxgPQkM9I5Tyj84hgAJyaag5V50fnTOOAaJwgaHIN5mE7cNRWkGPSpgb9r2Ly7fJ5pohpCfPxQ1gNbaty2YTcXtbAWdQvdtiE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=a9ktsqCW; arc=none smtp.client-ip=209.85.216.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="a9ktsqCW" Received: by mail-pj1-f53.google.com with SMTP id 98e67ed59e1d1-2d427fb7c92so1538692a91.1 for ; Tue, 20 Aug 2024 03:24:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724149453; x=1724754253; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LT89j+dp+gUlp+EdN6Q/RK32F1udlyN11SN0eEj1uLc=; b=a9ktsqCWxPDqQ1AcDnj0cQY0/j7/LKOp2+Hqj7WS8M641k6V+7kxUnZvLyaHPGj7Nm jq6HpuFmqyPw8QGX0/Wq7/wClOwYi5A+647jzPIBoI/uLX2ZjALtF4hG47ceuqAydWyJ O4N+idYkoPLjXKmBPNTMgT0kHbccJMFQ+/Ww6beInMertLHmwX5KdQuN0CQkFWyG9YZ/ zLP2dPmU/5soER2faH68Dg1w6wGNHg2dDyTVpITV5WlSOrkcxi9m199Tcd7gkOHallQn 4GbcLv2+87Qw+2NlP/uBngSZydIjtv9dL9tVF7AaQ6RfQ8mtJD5r/CtGnhvA1eIX3WPm EVAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724149453; x=1724754253; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LT89j+dp+gUlp+EdN6Q/RK32F1udlyN11SN0eEj1uLc=; b=h9QElnE6I1o/fb+gRsHEfiYHfL3CDLYrChTs4E/tGNJuY3bCFYhXni/SB1Bw78mVN8 iaP1p7PBlYIMti8hz5krZANLfPB+4rjPnkKqjeIhQZblqWxSl9cvYOKvi2Q/dGNZ79Vh bY7y053J2O0EnmX4cmLpePbdaSAIlcYXJdopwNADOhwppNn2TYLH+/puRYDbsAmqFQlg hLaPcrh7yWAVjm0msq73YbalNMUPbqu2ppuTbNc6pkETm681Q/QAx2WmbgAwnQNC1niJ hVRSQOfP3xRFyFEhGBmsuY/WWUj0nf23qH4l8Rb6KbMPeuNAiMDEKTNgeDP/WiJlvfKi xY4A== X-Gm-Message-State: AOJu0YzTcnPWs71uEQmtwOls7urnIqtPExiZBEFqNH7km3NmEJZPdCOE hU8VH2HjwtRIdAM+GLEmf2ZnsNTAVXhF5u+uQJcE7AU8GiUt+A/Rox2tP/Vo X-Google-Smtp-Source: AGHT+IFBB2xRLWcRScLI3JN/nuTmNX4X1g8AinZ8dCvW0JNBlngozyhLXXsZuGGv4D69geKrjSQk2g== X-Received: by 2002:a17:90a:de8b:b0:2c8:e888:26a2 with SMTP id 98e67ed59e1d1-2d3dfc6afa5mr13691121a91.13.1724149452761; Tue, 20 Aug 2024 03:24:12 -0700 (PDT) Received: from honey-badger.. ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d3e3174bfdsm8976166a91.27.2024.08.20.03.24.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Aug 2024 03:24:12 -0700 (PDT) From: Eduard Zingerman To: bpf@vger.kernel.org, ast@kernel.org Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, kernel-team@fb.com, yonghong.song@linux.dev, hffilwlqm@gmail.com, Eduard Zingerman Subject: [PATCH bpf-next v3 1/8] selftests/bpf: less spam in the log for message matching Date: Tue, 20 Aug 2024 03:23:49 -0700 Message-ID: <20240820102357.3372779-2-eddyz87@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240820102357.3372779-1-eddyz87@gmail.com> References: <20240820102357.3372779-1-eddyz87@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net When running test_loader based tests in the verbose mode each matched message leaves a trace in the stderr, e.g.: ./test_progs -vvv -t ... validate_msgs:PASS:expect_msg 0 nsec validate_msgs:PASS:expect_msg 0 nsec validate_msgs:PASS:expect_msg 0 nsec validate_msgs:PASS:expect_msg 0 nsec validate_msgs:PASS:expect_msg 0 nsec This is not very helpful when debugging such tests and clobbers the log a lot. Signed-off-by: Eduard Zingerman --- tools/testing/selftests/bpf/test_loader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c index 12b0c41e8d64..1b1290e090e7 100644 --- a/tools/testing/selftests/bpf/test_loader.c +++ b/tools/testing/selftests/bpf/test_loader.c @@ -531,7 +531,8 @@ static void validate_msgs(char *log_buf, struct expected_msgs *msgs, } } - if (!ASSERT_OK_PTR(match, "expect_msg")) { + if (!match) { + PRINT_FAIL("expect_msg\n"); if (env.verbosity == VERBOSE_NONE) emit_fn(log_buf, true /*force*/); for (j = 0; j <= i; j++) { From patchwork Tue Aug 20 10:23:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduard Zingerman X-Patchwork-Id: 13769858 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-pj1-f46.google.com (mail-pj1-f46.google.com [209.85.216.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CBC7F18E75A for ; Tue, 20 Aug 2024 10:24:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149456; cv=none; b=FXHvRQNRkMx4C44EwV07N6XV5e3dyPiSFyDIonUZ0g2VndIJAi2SKwvTxy0TL5wAfMplHBhKaAOOsRRH1Kl6gdbEKNFR/GzkNdW2QBHOk/hhBLdPyJclNSbGdTl8aoxotNICLXyKC+t5PEL7xPhHV2j1ItdyBc8uyUGVnuF/Khw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149456; c=relaxed/simple; bh=yVxPsa6gCWsiCW3AJxdjRC7LaGSAYzijbIZJtLytf/w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t9S8zb6Bn/7lRn2WFCPz3BBON7F82K/r7H7+XuAlyVyDB0NX3OHtoErfKV0m/bevrRPOvuvfJmLpRzgQ0W2SSQK3GPfx1KHs710ytn/pgZtWa0lLseMw1lM9FELqFpxnC58p0C/LqshSRzahOJyyCKBMKvAQ/zT9bMqbYtUCgW8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bqkjv7Zr; arc=none smtp.client-ip=209.85.216.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bqkjv7Zr" Received: by mail-pj1-f46.google.com with SMTP id 98e67ed59e1d1-2d3c05dc63eso3901931a91.0 for ; Tue, 20 Aug 2024 03:24:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724149454; x=1724754254; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GzcUh7QEGUq6bk63EgLsrBYkdCv0nG08nmJodSuJF+8=; b=bqkjv7ZrbUZjAcwodjEgNyACFpeZlzkohXh6LP+LWypiaSHI6uCEgBNeK37z4wEjGe iEl4boksel686Uxm38SiNZwI2Mrc7L2J4nFg9tDAkvRTIzJsplkgWLm8HIYhN0ScjYoR uER+oq6xWv3BUWycl4qGsJh8vH+rOc8GyQZXiOSM8/mCcpPGqBV9N8P/82N9E7xjo+zu PlSmpwlUxsjRdpITEhmpM4HBGKqQbYW3c/AbA+ov5TTmwrrbKa+W+/DNf37gMaOaPgWw mxDuyFKtnO+IneSzGAudcR47w226Wa5w1yQ2y5Fv89KMi0GTdML5s4eVbZt1aS0GlPPX 6u8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724149454; x=1724754254; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GzcUh7QEGUq6bk63EgLsrBYkdCv0nG08nmJodSuJF+8=; b=ex7H6W7EPz0ndj6sR+L1NZH47gwx9J7ylrCZtsKDfv1uhFyXj5iiNNh2zXDTINj4bS 8ArKL4NldC9z3nLEttTxUkcJ4+qC+xP5P8NRX5t8lmKh01jay+e+5j1AQLShKaNmFkhH mC5h7VjkPkCSDD7/QkubRL4VvKSKQY+N/ytFRm1k3PfJz3T4sHFLeY5uFV5ncwK4OdVK hY0JBBlGAVswLZ9Jq5aFrxuQqtZT6+I0mtT8Jrduz+l+MKESl3+t6g1D8YRbPRaN3I5Q jQgidre76w/ProA565msBQwVX2FuZURm7q1yPdhXKaWvDmSKaYMv93+NRH2GcV6wgEl+ unQw== X-Gm-Message-State: AOJu0YzSfdUO4YQhTasF24+N9XcTu+ENtGBZ7XtSZnbN8FcjSYblIR2J sUtjK1Cl5nH5574xyBPzKctHEp92RbWS7Swtj+hzs2d69Rz1mHONHNkEWBgX X-Google-Smtp-Source: AGHT+IHET56YtQoEBEbhg9jrFb71+YuKppv8B6UgRyFHn7brFqRUeza9ByP/O/XRbCx7YWumMxtZ+g== X-Received: by 2002:a17:90a:8401:b0:2d0:d82:60ae with SMTP id 98e67ed59e1d1-2d5c0ed2a32mr2005866a91.37.1724149453837; Tue, 20 Aug 2024 03:24:13 -0700 (PDT) Received: from honey-badger.. ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d3e3174bfdsm8976166a91.27.2024.08.20.03.24.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Aug 2024 03:24:13 -0700 (PDT) From: Eduard Zingerman To: bpf@vger.kernel.org, ast@kernel.org Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, kernel-team@fb.com, yonghong.song@linux.dev, hffilwlqm@gmail.com, Eduard Zingerman Subject: [PATCH bpf-next v3 2/8] selftests/bpf: correctly move 'log' upon successful match Date: Tue, 20 Aug 2024 03:23:50 -0700 Message-ID: <20240820102357.3372779-3-eddyz87@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240820102357.3372779-1-eddyz87@gmail.com> References: <20240820102357.3372779-1-eddyz87@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Suppose log="foo bar buz" and msg->substr="bar". In such case current match processing logic would update 'log' as follows: log += strlen(msg->substr); -> log += 3 -> log=" bar". However, the intent behind the 'log' update is to make it point after the successful match, e.g. to make log=" buz" in the example above. Fixes: 4ef5d6af4935 ("selftests/bpf: no need to track next_match_pos in struct test_loader") Signed-off-by: Eduard Zingerman --- tools/testing/selftests/bpf/test_loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c index 1b1290e090e7..f5f5d16ac550 100644 --- a/tools/testing/selftests/bpf/test_loader.c +++ b/tools/testing/selftests/bpf/test_loader.c @@ -522,7 +522,7 @@ static void validate_msgs(char *log_buf, struct expected_msgs *msgs, if (msg->substr) { match = strstr(log, msg->substr); if (match) - log += strlen(msg->substr); + log = match + strlen(msg->substr); } else { err = regexec(&msg->regex, log, 1, reg_match, 0); if (err == 0) { From patchwork Tue Aug 20 10:23:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduard Zingerman X-Patchwork-Id: 13769859 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-pg1-f174.google.com (mail-pg1-f174.google.com [209.85.215.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2C3B18E777 for ; Tue, 20 Aug 2024 10:24:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149457; cv=none; b=kTcydzHzh43LCoRzJnEfjumqlWEz/xgedM/frTtlTtno4vOvm3N7Fd3XU6ontJWfHTaxfKTZ3E4rUYSW2PQJpXylVFggBXXfDhOpRrEkskxDwKJKQeeG3ZLqDEfZLDAdj32eXHYannkK2zyhEu196zPKBqXz+DzTUdCQ5LhGl/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149457; c=relaxed/simple; bh=CP3j8P9oCjLejwVeg3t9skFTS9910f9FzEPrtMdaJRc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pcFQAsFe4Yiwk3BM43GapPGm/kTIxv8m0tQlRGUJ/hBrszUWxG/RPvrpBAInbFKd6588TGZd657WA7k0WcYw4IWxGIPDaS026ADvGVHeLtdEemoAjxey8jCS6fJgOq19aCp6WGWBxHtui13BtwJi6t5FQz/QDKPeKM6QfZZuSxs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=H4T7c9t3; arc=none smtp.client-ip=209.85.215.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="H4T7c9t3" Received: by mail-pg1-f174.google.com with SMTP id 41be03b00d2f7-7afd1aeac83so4181666a12.0 for ; Tue, 20 Aug 2024 03:24:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724149455; x=1724754255; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=++j0dC+7bK15CEdljY1lUn2fuean9+wtaZWzhBX4JRU=; b=H4T7c9t3Z5tpXOfcc90DJPw32/SNg3Ij2sKYRQwNKbYCVVx5Il5CuQMtMfT7db6Kzc bpp7m116QLW9+8Upm01K0K/Ma1IyWDPnbN5z3WjJLT08yyavaMj9e4uvm3xVQ1Ay5+WX mJ5esRzWHTRUTbJP6WT5tWkXOThDEndlWB1nkd1j34ebyLXBqkdNcWSaFMrbKR99aC50 gY0oJ14DffINIKBYIKo9Ydospbq15fZynHnTDZri4EZ47WSnZoOmM3YqzO7JfJR+hr/z OvzaXQyltvi+TFVj4/NyiZ7pqj0eoOgAPgcJ5eSkzxD9OPoD2ZPv72pSpAmKaz1gNS/u tP9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724149455; x=1724754255; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=++j0dC+7bK15CEdljY1lUn2fuean9+wtaZWzhBX4JRU=; b=YCiHpHSVALrzkfk1Olt+YdR478m6egyPiycPet1E2YlghHvFvMCnkXmmvx+9zM6gt6 i4zRGFcOHp6/RvFi8DXaHJRuV4qGwoDAZ2mVbjEIEngIzZ3+WfwzhD3R6wEDvthk0f/j P2Sfxszy0ZkfkYY57//kEiQHOtbH3ywkjyu5G3BFZxfGVjvSxvrJngAO75fGOqWwzGQk 4tNpW1xq+oPGGlVIPH+V904Jbe2sqg09wb9GHn7lW8qpEVtEL07DW0Uvs9yOPeZnz9A/ 4MnH8VJionFVuAxYCqvglc1XIsMQLgXbjg0jGWMXX9jDWMDu/I7+fS0mPk+8VwE4Xc9r qrrA== X-Gm-Message-State: AOJu0Yy5iAQ679zO4RBEjDxm2ByzECVn4+65NYgW7bru+Ck5B7eut/13 16JxZG49MlIhRuimWs0Z9OV3S31/0lcQIeK5j34WfTBS/CrbulaWpxYHdcAd X-Google-Smtp-Source: AGHT+IHoSfe/yKfffQNYGVBt5nIrfdJi11rhUTSSFSIuhwc4qPvj51WJpCeqeb1gG1ZAiJAU4LE2SA== X-Received: by 2002:a17:90b:1e12:b0:2c9:75a7:5c25 with SMTP id 98e67ed59e1d1-2d4733ff749mr3727785a91.15.1724149454872; Tue, 20 Aug 2024 03:24:14 -0700 (PDT) Received: from honey-badger.. ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d3e3174bfdsm8976166a91.27.2024.08.20.03.24.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Aug 2024 03:24:14 -0700 (PDT) From: Eduard Zingerman To: bpf@vger.kernel.org, ast@kernel.org Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, kernel-team@fb.com, yonghong.song@linux.dev, hffilwlqm@gmail.com, Eduard Zingerman Subject: [PATCH bpf-next v3 3/8] selftests/bpf: fix to avoid __msg tag de-duplication by clang Date: Tue, 20 Aug 2024 03:23:51 -0700 Message-ID: <20240820102357.3372779-4-eddyz87@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240820102357.3372779-1-eddyz87@gmail.com> References: <20240820102357.3372779-1-eddyz87@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net __msg, __regex and __xlated tags are based on __attribute__((btf_decl_tag("..."))) annotations. Clang de-duplicates such annotations, e.g. the following two sequences of tags are identical in final BTF: /* seq A */ /* seq B */ __tag("foo") __tag("foo") __tag("bar") __tag("bar") __tag("foo") Fix this by adding a unique suffix for each tag using __COUNTER__ pre-processor macro. E.g. here is a new definition for __msg: #define __msg(msg) \ __attribute__((btf_decl_tag("comment:test_expect_msg=" XSTR(__COUNTER__) "=" msg))) Using this definition the "seq A" from example above is translated to BTF as follows: [..] DECL_TAG 'comment:test_expect_msg=0=foo' type_id=X component_idx=-1 [..] DECL_TAG 'comment:test_expect_msg=1=bar' type_id=X component_idx=-1 [..] DECL_TAG 'comment:test_expect_msg=2=foo' type_id=X component_idx=-1 Surprisingly, this bug affects a single existing test: verifier_spill_fill/old_stack_misc_vs_cur_ctx_ptr, where sequence of identical messages was expected in the log. Fixes: 537c3f66eac1 ("selftests/bpf: add generic BPF program tester-loader") Signed-off-by: Eduard Zingerman --- tools/testing/selftests/bpf/progs/bpf_misc.h | 15 +++--- .../selftests/bpf/progs/verifier_spill_fill.c | 8 ++-- tools/testing/selftests/bpf/test_loader.c | 47 ++++++++++++++----- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h index a225cd87897c..4f1029743734 100644 --- a/tools/testing/selftests/bpf/progs/bpf_misc.h +++ b/tools/testing/selftests/bpf/progs/bpf_misc.h @@ -2,6 +2,9 @@ #ifndef __BPF_MISC_H__ #define __BPF_MISC_H__ +#define XSTR(s) STR(s) +#define STR(s) #s + /* This set of attributes controls behavior of the * test_loader.c:test_loader__run_subtests(). * @@ -68,15 +71,15 @@ * Several __arch_* annotations could be specified at once. * When test case is not run on current arch it is marked as skipped. */ -#define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" msg))) -#define __regex(regex) __attribute__((btf_decl_tag("comment:test_expect_regex=" regex))) -#define __xlated(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated=" msg))) +#define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" XSTR(__COUNTER__) "=" msg))) +#define __regex(regex) __attribute__((btf_decl_tag("comment:test_expect_regex=" XSTR(__COUNTER__) "=" regex))) +#define __xlated(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated=" XSTR(__COUNTER__) "=" msg))) #define __failure __attribute__((btf_decl_tag("comment:test_expect_failure"))) #define __success __attribute__((btf_decl_tag("comment:test_expect_success"))) #define __description(desc) __attribute__((btf_decl_tag("comment:test_description=" desc))) -#define __msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" msg))) -#define __regex_unpriv(regex) __attribute__((btf_decl_tag("comment:test_expect_regex_unpriv=" regex))) -#define __xlated_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" msg))) +#define __msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" XSTR(__COUNTER__) "=" msg))) +#define __regex_unpriv(regex) __attribute__((btf_decl_tag("comment:test_expect_regex_unpriv=" XSTR(__COUNTER__) "=" regex))) +#define __xlated_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" XSTR(__COUNTER__) "=" msg))) #define __failure_unpriv __attribute__((btf_decl_tag("comment:test_expect_failure_unpriv"))) #define __success_unpriv __attribute__((btf_decl_tag("comment:test_expect_success_unpriv"))) #define __log_level(lvl) __attribute__((btf_decl_tag("comment:test_log_level="#lvl))) diff --git a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c index 9d288ec7a168..671d9f415dbf 100644 --- a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c +++ b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c @@ -1213,10 +1213,10 @@ __success __log_level(2) * - once for path entry - label 2; * - once for path entry - label 1 - label 2. */ -__msg("r1 = *(u64 *)(r10 -8)") -__msg("exit") -__msg("r1 = *(u64 *)(r10 -8)") -__msg("exit") +__msg("8: (79) r1 = *(u64 *)(r10 -8)") +__msg("9: (95) exit") +__msg("from 2 to 7") +__msg("8: safe") __msg("processed 11 insns") __flag(BPF_F_TEST_STATE_FREQ) __naked void old_stack_misc_vs_cur_ctx_ptr(void) diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c index f5f5d16ac550..c604a82e03c4 100644 --- a/tools/testing/selftests/bpf/test_loader.c +++ b/tools/testing/selftests/bpf/test_loader.c @@ -215,6 +215,35 @@ static void update_flags(int *flags, int flag, bool clear) *flags |= flag; } +/* Matches a string of form '[^=]=.*' and returns it's suffix. + * Used to parse btf_decl_tag values. + * Such values require unique prefix because compiler does not add + * same __attribute__((btf_decl_tag(...))) twice. + * Test suite uses two-component tags for such cases: + * + * __COUNTER__ '=' + * + * For example, two consecutive __msg tags '__msg("foo") __msg("foo")' + * would be encoded as: + * + * [18] DECL_TAG 'comment:test_expect_msg=0=foo' type_id=15 component_idx=-1 + * [19] DECL_TAG 'comment:test_expect_msg=1=foo' type_id=15 component_idx=-1 + * + * And the purpose of this function is to extract 'foo' from the above. + */ +static const char *skip_dynamic_pfx(const char *s, const char *pfx) +{ + const char *msg; + + if (strncmp(s, pfx, strlen(pfx)) != 0) + return NULL; + msg = s + strlen(pfx); + msg = strchr(msg, '='); + if (!msg) + return NULL; + return msg + 1; +} + enum arch { ARCH_X86_64 = 0x1, ARCH_ARM64 = 0x2, @@ -290,38 +319,32 @@ static int parse_test_spec(struct test_loader *tester, } else if (strcmp(s, TEST_TAG_AUXILIARY_UNPRIV) == 0) { spec->auxiliary = true; spec->mode_mask |= UNPRIV; - } else if (str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX)) { - msg = s + sizeof(TEST_TAG_EXPECT_MSG_PFX) - 1; + } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX))) { err = push_msg(msg, NULL, &spec->priv.expect_msgs); if (err) goto cleanup; spec->mode_mask |= PRIV; - } else if (str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV)) { - msg = s + sizeof(TEST_TAG_EXPECT_MSG_PFX_UNPRIV) - 1; + } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV))) { err = push_msg(msg, NULL, &spec->unpriv.expect_msgs); if (err) goto cleanup; spec->mode_mask |= UNPRIV; - } else if (str_has_pfx(s, TEST_TAG_EXPECT_REGEX_PFX)) { - msg = s + sizeof(TEST_TAG_EXPECT_REGEX_PFX) - 1; + } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_REGEX_PFX))) { err = push_msg(NULL, msg, &spec->priv.expect_msgs); if (err) goto cleanup; spec->mode_mask |= PRIV; - } else if (str_has_pfx(s, TEST_TAG_EXPECT_REGEX_PFX_UNPRIV)) { - msg = s + sizeof(TEST_TAG_EXPECT_REGEX_PFX_UNPRIV) - 1; + } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_REGEX_PFX_UNPRIV))) { err = push_msg(NULL, msg, &spec->unpriv.expect_msgs); if (err) goto cleanup; spec->mode_mask |= UNPRIV; - } else if (str_has_pfx(s, TEST_TAG_EXPECT_XLATED_PFX)) { - msg = s + sizeof(TEST_TAG_EXPECT_XLATED_PFX) - 1; + } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX))) { err = push_msg(msg, NULL, &spec->priv.expect_xlated); if (err) goto cleanup; spec->mode_mask |= PRIV; - } else if (str_has_pfx(s, TEST_TAG_EXPECT_XLATED_PFX_UNPRIV)) { - msg = s + sizeof(TEST_TAG_EXPECT_XLATED_PFX_UNPRIV) - 1; + } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX_UNPRIV))) { err = push_msg(msg, NULL, &spec->unpriv.expect_xlated); if (err) goto cleanup; From patchwork Tue Aug 20 10:23:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduard Zingerman X-Patchwork-Id: 13769860 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7502F18DF6A for ; Tue, 20 Aug 2024 10:24:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149459; cv=none; b=F3y2zLJ8ZKRaSfgeGQTdsHGebyEBLoD2DpIyfFFGE5DRVBKSvFbgimIUXnrJ+kjkMMGqxg2ZenK2QdVsnI6O4XQhgfaJ+Wv3tspMGzNiV4I4zJ6Ha20We2liyzA/XKlu6peOlJDyHW/7sxoC8gYVPOVWi3pk9aAfpSGtlUnLJ40= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149459; c=relaxed/simple; bh=yl7NGAqy6seSPAqTOYSyg5/ksswDtqTU7hTfLXM+7z0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fzD2crQbVKrtFoX+ZIHnBVqbCwDOeRx5dZyxcAm8gVwH31NG2vQIKSRlugV4KBkf6bhhL16eAWfbi517fIi0HNSvi593e9S6t8RBtFitXvooZ0dRoLQrw8zmEamyDfgke6NefjHOk6Trp8RDPTSVU9moZ1BMlhSxhlOw6dyn5aA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TKYuLWnr; arc=none smtp.client-ip=209.85.210.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TKYuLWnr" Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-70d1c655141so3394503b3a.1 for ; Tue, 20 Aug 2024 03:24:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724149456; x=1724754256; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=OTVbxIR/I2bJtJ0sOwaKg/sfadnkaNcta9pDs+5+wMU=; b=TKYuLWnrrDCQVm+Y8iE2RTPsJ9nENoepdrr8HxxBcEZLYnqLACPiZOaZQq1whHWF4U nD806/gccCD13qAbKv+ooCzrtJOvIeeSqGnwSYh8Lc6S++hc0M5bfvV8atq9g2iJDiZV qq7Anz71L4XOT6b7/OpD29bTaXv41on0pQmrImNXJARamZww6nQp/Lg+fFNX/GbJafw2 NfsjBf6MgupxHVBJhAjZv6OJLHUWXl2T/QrM00eulCYmjC+wqn1qO4wsc7wsZFTr8EW9 1X/zd2ZuEo6R0WRFv7L6//dRCOOfyWkb8lUda/NIG7hAhih8oz7WKPGbc6LrkTkDG52e Qp9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724149456; x=1724754256; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OTVbxIR/I2bJtJ0sOwaKg/sfadnkaNcta9pDs+5+wMU=; b=WJuQInNdMKgbT4OF8eNwHoMM8N+07db7pLsPqzMcXREKa0GWGpve7b4YywE/pf7UXG Y1oQRIzHcSc07dL6VQxp0oFLjHt1tcc5c7eThpF6jHSZ7CHDPe9Hycy19KKEWL5nEbCi 0rVEzq8V25jZtz5fR5ge37es4SOLCzbcTn0eblCBBOfnDHuwnZceXsHLRWH6rLS7ZW8h uWjMPiUKcmuYOGJHmjo7cpAgJKQvn9WZGpsj4UftZWMZ3OsYk8SkhM8skIX1WQDmm6SG gPjLE/S/Su1oz2Kyipi3CUD1GXNNTihTfxgNTzYWAJhsxavjMes59ttdFDWZAgP9oTAu XplQ== X-Gm-Message-State: AOJu0YwqKnM8s8BUHxrrO6cj961jgjd3Qr1yBXKxG5KXET2FFpaAohlV 3a+n5MtEorHQloELhXwMIzL+3Kyoiuh++BtRoD8Bq+J7bv/LYkzI2yKLLLWs X-Google-Smtp-Source: AGHT+IEsMRtf/4BW1lCZKEizOOoV1I5Unz93zU9J8Kidgq8SGGyeYfIVGT9bNo4TGuavJIjH3pKi4A== X-Received: by 2002:a05:6a20:d490:b0:1c2:8dd5:71d9 with SMTP id adf61e73a8af0-1c904f6bab9mr12854933637.4.1724149455928; Tue, 20 Aug 2024 03:24:15 -0700 (PDT) Received: from honey-badger.. ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d3e3174bfdsm8976166a91.27.2024.08.20.03.24.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Aug 2024 03:24:15 -0700 (PDT) From: Eduard Zingerman To: bpf@vger.kernel.org, ast@kernel.org Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, kernel-team@fb.com, yonghong.song@linux.dev, hffilwlqm@gmail.com, Eduard Zingerman Subject: [PATCH bpf-next v3 4/8] selftests/bpf: replace __regex macro with "{{...}}" patterns Date: Tue, 20 Aug 2024 03:23:52 -0700 Message-ID: <20240820102357.3372779-5-eddyz87@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240820102357.3372779-1-eddyz87@gmail.com> References: <20240820102357.3372779-1-eddyz87@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Upcoming changes require a notation to specify regular expression matches for regular verifier log messages, disassembly of BPF instructions, disassembly of jited instructions. Neither basic nor extended POSIX regular expressions w/o additional escaping are good for this role because of wide use of special characters in disassembly, for example: movq -0x10(%rbp), %rax ;; () are special characters cmpq $0x21, %rax ;; $ is a special character *(u64 *)(r10 -16) = r1 ;; * and () are special characters This commit borrows syntax from LLVM's FileCheck utility. It replaces __regex macro with ability to embed regular expressions in __msg patters using "{{" "}}" pairs for escaping. Syntax for __msg patterns: pattern := ( | regex)* regex := "{{" "}}" For example, pattern "foo{{[0-9]+}}" matches strings like "foo0", "foo007", etc. Signed-off-by: Eduard Zingerman --- tools/testing/selftests/bpf/progs/bpf_misc.h | 9 +- .../testing/selftests/bpf/progs/dynptr_fail.c | 6 +- .../testing/selftests/bpf/progs/rbtree_fail.c | 2 +- .../bpf/progs/refcounted_kptr_fail.c | 4 +- tools/testing/selftests/bpf/test_loader.c | 164 +++++++++++------- 5 files changed, 115 insertions(+), 70 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h index 4f1029743734..cc3ef20a6490 100644 --- a/tools/testing/selftests/bpf/progs/bpf_misc.h +++ b/tools/testing/selftests/bpf/progs/bpf_misc.h @@ -25,12 +25,15 @@ * * __msg Message expected to be found in the verifier log. * Multiple __msg attributes could be specified. + * To match a regular expression use "{{" "}}" brackets, + * e.g. "foo{{[0-9]+}}" matches strings like "foo007". + * Extended POSIX regular expression syntax is allowed + * inside the brackets. * __msg_unpriv Same as __msg but for unprivileged mode. * - * __regex Same as __msg, but using a regular expression. - * __regex_unpriv Same as __msg_unpriv but using a regular expression. * __xlated Expect a line in a disassembly log after verifier applies rewrites. * Multiple __xlated attributes could be specified. + * Regular expressions could be specified same way as in __msg. * __xlated_unpriv Same as __xlated but for unprivileged mode. * * __success Expect program load success in privileged mode. @@ -72,13 +75,11 @@ * When test case is not run on current arch it is marked as skipped. */ #define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" XSTR(__COUNTER__) "=" msg))) -#define __regex(regex) __attribute__((btf_decl_tag("comment:test_expect_regex=" XSTR(__COUNTER__) "=" regex))) #define __xlated(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated=" XSTR(__COUNTER__) "=" msg))) #define __failure __attribute__((btf_decl_tag("comment:test_expect_failure"))) #define __success __attribute__((btf_decl_tag("comment:test_expect_success"))) #define __description(desc) __attribute__((btf_decl_tag("comment:test_description=" desc))) #define __msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" XSTR(__COUNTER__) "=" msg))) -#define __regex_unpriv(regex) __attribute__((btf_decl_tag("comment:test_expect_regex_unpriv=" XSTR(__COUNTER__) "=" regex))) #define __xlated_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" XSTR(__COUNTER__) "=" msg))) #define __failure_unpriv __attribute__((btf_decl_tag("comment:test_expect_failure_unpriv"))) #define __success_unpriv __attribute__((btf_decl_tag("comment:test_expect_success_unpriv"))) diff --git a/tools/testing/selftests/bpf/progs/dynptr_fail.c b/tools/testing/selftests/bpf/progs/dynptr_fail.c index e35bc1eac52a..68b8c6eca508 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_fail.c +++ b/tools/testing/selftests/bpf/progs/dynptr_fail.c @@ -964,7 +964,7 @@ int dynptr_invalidate_slice_reinit(void *ctx) * mem_or_null pointers. */ SEC("?raw_tp") -__failure __regex("R[0-9]+ type=scalar expected=percpu_ptr_") +__failure __msg("R{{[0-9]+}} type=scalar expected=percpu_ptr_") int dynptr_invalidate_slice_or_null(void *ctx) { struct bpf_dynptr ptr; @@ -982,7 +982,7 @@ int dynptr_invalidate_slice_or_null(void *ctx) /* Destruction of dynptr should also any slices obtained from it */ SEC("?raw_tp") -__failure __regex("R[0-9]+ invalid mem access 'scalar'") +__failure __msg("R{{[0-9]+}} invalid mem access 'scalar'") int dynptr_invalidate_slice_failure(void *ctx) { struct bpf_dynptr ptr1; @@ -1069,7 +1069,7 @@ int dynptr_read_into_slot(void *ctx) /* bpf_dynptr_slice()s are read-only and cannot be written to */ SEC("?tc") -__failure __regex("R[0-9]+ cannot write into rdonly_mem") +__failure __msg("R{{[0-9]+}} cannot write into rdonly_mem") int skb_invalid_slice_write(struct __sk_buff *skb) { struct bpf_dynptr ptr; diff --git a/tools/testing/selftests/bpf/progs/rbtree_fail.c b/tools/testing/selftests/bpf/progs/rbtree_fail.c index b722a1e1ddef..dbd5eee8e25e 100644 --- a/tools/testing/selftests/bpf/progs/rbtree_fail.c +++ b/tools/testing/selftests/bpf/progs/rbtree_fail.c @@ -105,7 +105,7 @@ long rbtree_api_remove_unadded_node(void *ctx) } SEC("?tc") -__failure __regex("Unreleased reference id=3 alloc_insn=[0-9]+") +__failure __msg("Unreleased reference id=3 alloc_insn={{[0-9]+}}") long rbtree_api_remove_no_drop(void *ctx) { struct bpf_rb_node *res; diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c b/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c index f8d4b7cfcd68..836c8ab7b908 100644 --- a/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c +++ b/tools/testing/selftests/bpf/progs/refcounted_kptr_fail.c @@ -32,7 +32,7 @@ static bool less(struct bpf_rb_node *a, const struct bpf_rb_node *b) } SEC("?tc") -__failure __regex("Unreleased reference id=4 alloc_insn=[0-9]+") +__failure __msg("Unreleased reference id=4 alloc_insn={{[0-9]+}}") long rbtree_refcounted_node_ref_escapes(void *ctx) { struct node_acquire *n, *m; @@ -73,7 +73,7 @@ long refcount_acquire_maybe_null(void *ctx) } SEC("?tc") -__failure __regex("Unreleased reference id=3 alloc_insn=[0-9]+") +__failure __msg("Unreleased reference id=3 alloc_insn={{[0-9]+}}") long rbtree_refcounted_node_ref_escapes_owning_input(void *ctx) { struct node_acquire *n, *m; diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c index c604a82e03c4..b0d7158e00c1 100644 --- a/tools/testing/selftests/bpf/test_loader.c +++ b/tools/testing/selftests/bpf/test_loader.c @@ -19,12 +19,10 @@ #define TEST_TAG_EXPECT_FAILURE "comment:test_expect_failure" #define TEST_TAG_EXPECT_SUCCESS "comment:test_expect_success" #define TEST_TAG_EXPECT_MSG_PFX "comment:test_expect_msg=" -#define TEST_TAG_EXPECT_REGEX_PFX "comment:test_expect_regex=" #define TEST_TAG_EXPECT_XLATED_PFX "comment:test_expect_xlated=" #define TEST_TAG_EXPECT_FAILURE_UNPRIV "comment:test_expect_failure_unpriv" #define TEST_TAG_EXPECT_SUCCESS_UNPRIV "comment:test_expect_success_unpriv" #define TEST_TAG_EXPECT_MSG_PFX_UNPRIV "comment:test_expect_msg_unpriv=" -#define TEST_TAG_EXPECT_REGEX_PFX_UNPRIV "comment:test_expect_regex_unpriv=" #define TEST_TAG_EXPECT_XLATED_PFX_UNPRIV "comment:test_expect_xlated_unpriv=" #define TEST_TAG_LOG_LEVEL_PFX "comment:test_log_level=" #define TEST_TAG_PROG_FLAGS_PFX "comment:test_prog_flags=" @@ -55,8 +53,9 @@ enum mode { struct expect_msg { const char *substr; /* substring match */ - const char *regex_str; /* regex-based match */ regex_t regex; + bool is_regex; + bool on_next_line; }; struct expected_msgs { @@ -111,7 +110,7 @@ static void free_msgs(struct expected_msgs *msgs) int i; for (i = 0; i < msgs->cnt; i++) - if (msgs->patterns[i].regex_str) + if (msgs->patterns[i].is_regex) regfree(&msgs->patterns[i].regex); free(msgs->patterns); msgs->patterns = NULL; @@ -132,12 +131,71 @@ static void free_test_spec(struct test_spec *spec) spec->unpriv.name = NULL; } -static int push_msg(const char *substr, const char *regex_str, struct expected_msgs *msgs) +/* Compiles regular expression matching pattern. + * Pattern has a special syntax: + * + * pattern := ( | regex)* + * regex := "{{" "}}" + * + * In other words, pattern is a verbatim text with inclusion + * of regular expressions enclosed in "{{" "}}" pairs. + * For example, pattern "foo{{[0-9]+}}" matches strings like + * "foo0", "foo007", etc. + */ +static int compile_regex(const char *pattern, regex_t *regex) +{ + char err_buf[256], buf[256] = {}, *ptr, *buf_end; + const char *original_pattern = pattern; + bool in_regex = false; + int err; + + buf_end = buf + sizeof(buf); + ptr = buf; + while (*pattern && ptr < buf_end - 2) { + if (!in_regex && str_has_pfx(pattern, "{{")) { + in_regex = true; + pattern += 2; + continue; + } + if (in_regex && str_has_pfx(pattern, "}}")) { + in_regex = false; + pattern += 2; + continue; + } + if (in_regex) { + *ptr++ = *pattern++; + continue; + } + /* list of characters that need escaping for extended posix regex */ + if (strchr(".[]\\()*+?{}|^$", *pattern)) { + *ptr++ = '\\'; + *ptr++ = *pattern++; + continue; + } + *ptr++ = *pattern++; + } + if (*pattern) { + PRINT_FAIL("Regexp too long: '%s'\n", original_pattern); + return -EINVAL; + } + if (in_regex) { + PRINT_FAIL("Regexp has open '{{' but no closing '}}': '%s'\n", original_pattern); + return -EINVAL; + } + err = regcomp(regex, buf, REG_EXTENDED | REG_NEWLINE); + if (err != 0) { + regerror(err, regex, err_buf, sizeof(err_buf)); + PRINT_FAIL("Regexp compilation error in '%s': '%s'\n", buf, err_buf); + return -EINVAL; + } + return 0; +} + +static int __push_msg(const char *pattern, bool on_next_line, struct expected_msgs *msgs) { - void *tmp; - int regcomp_res; - char error_msg[100]; struct expect_msg *msg; + void *tmp; + int err; tmp = realloc(msgs->patterns, (1 + msgs->cnt) * sizeof(struct expect_msg)); @@ -147,26 +205,38 @@ static int push_msg(const char *substr, const char *regex_str, struct expected_m } msgs->patterns = tmp; msg = &msgs->patterns[msgs->cnt]; - - if (substr) { - msg->substr = substr; - msg->regex_str = NULL; - } else { - msg->regex_str = regex_str; - msg->substr = NULL; - regcomp_res = regcomp(&msg->regex, regex_str, REG_EXTENDED|REG_NEWLINE); - if (regcomp_res != 0) { - regerror(regcomp_res, &msg->regex, error_msg, sizeof(error_msg)); - PRINT_FAIL("Regexp compilation error in '%s': '%s'\n", - regex_str, error_msg); - return -EINVAL; - } + msg->on_next_line = on_next_line; + msg->substr = pattern; + msg->is_regex = false; + if (strstr(pattern, "{{")) { + err = compile_regex(pattern, &msg->regex); + if (err) + return err; + msg->is_regex = true; } - msgs->cnt += 1; return 0; } +static int clone_msgs(struct expected_msgs *from, struct expected_msgs *to) +{ + struct expect_msg *msg; + int i, err; + + for (i = 0; i < from->cnt; i++) { + msg = &from->patterns[i]; + err = __push_msg(msg->substr, msg->on_next_line, to); + if (err) + return err; + } + return 0; +} + +static int push_msg(const char *substr, struct expected_msgs *msgs) +{ + return __push_msg(substr, false, msgs); +} + static int parse_int(const char *str, int *val, const char *name) { char *end; @@ -320,32 +390,22 @@ static int parse_test_spec(struct test_loader *tester, spec->auxiliary = true; spec->mode_mask |= UNPRIV; } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX))) { - err = push_msg(msg, NULL, &spec->priv.expect_msgs); + err = push_msg(msg, &spec->priv.expect_msgs); if (err) goto cleanup; spec->mode_mask |= PRIV; } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV))) { - err = push_msg(msg, NULL, &spec->unpriv.expect_msgs); - if (err) - goto cleanup; - spec->mode_mask |= UNPRIV; - } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_REGEX_PFX))) { - err = push_msg(NULL, msg, &spec->priv.expect_msgs); - if (err) - goto cleanup; - spec->mode_mask |= PRIV; - } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_REGEX_PFX_UNPRIV))) { - err = push_msg(NULL, msg, &spec->unpriv.expect_msgs); + err = push_msg(msg, &spec->unpriv.expect_msgs); if (err) goto cleanup; spec->mode_mask |= UNPRIV; } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX))) { - err = push_msg(msg, NULL, &spec->priv.expect_xlated); + err = push_msg(msg, &spec->priv.expect_xlated); if (err) goto cleanup; spec->mode_mask |= PRIV; } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX_UNPRIV))) { - err = push_msg(msg, NULL, &spec->unpriv.expect_xlated); + err = push_msg(msg, &spec->unpriv.expect_xlated); if (err) goto cleanup; spec->mode_mask |= UNPRIV; @@ -457,26 +517,10 @@ static int parse_test_spec(struct test_loader *tester, spec->unpriv.execute = spec->priv.execute; } - if (spec->unpriv.expect_msgs.cnt == 0) { - for (i = 0; i < spec->priv.expect_msgs.cnt; i++) { - struct expect_msg *msg = &spec->priv.expect_msgs.patterns[i]; - - err = push_msg(msg->substr, msg->regex_str, - &spec->unpriv.expect_msgs); - if (err) - goto cleanup; - } - } - if (spec->unpriv.expect_xlated.cnt == 0) { - for (i = 0; i < spec->priv.expect_xlated.cnt; i++) { - struct expect_msg *msg = &spec->priv.expect_xlated.patterns[i]; - - err = push_msg(msg->substr, msg->regex_str, - &spec->unpriv.expect_xlated); - if (err) - goto cleanup; - } - } + if (spec->unpriv.expect_msgs.cnt == 0) + clone_msgs(&spec->priv.expect_msgs, &spec->unpriv.expect_msgs); + if (spec->unpriv.expect_xlated.cnt == 0) + clone_msgs(&spec->priv.expect_xlated, &spec->unpriv.expect_xlated); } spec->valid = true; @@ -542,7 +586,7 @@ static void validate_msgs(char *log_buf, struct expected_msgs *msgs, struct expect_msg *msg = &msgs->patterns[i]; const char *match = NULL; - if (msg->substr) { + if (!msg->is_regex) { match = strstr(log, msg->substr); if (match) log = match + strlen(msg->substr); @@ -562,8 +606,8 @@ static void validate_msgs(char *log_buf, struct expected_msgs *msgs, msg = &msgs->patterns[j]; fprintf(stderr, "%s %s: '%s'\n", j < i ? "MATCHED " : "EXPECTED", - msg->substr ? "SUBSTR" : " REGEX", - msg->substr ?: msg->regex_str); + msg->is_regex ? " REGEX" : "SUBSTR", + msg->substr); } return; } From patchwork Tue Aug 20 10:23:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduard Zingerman X-Patchwork-Id: 13769861 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1906418EFC6 for ; Tue, 20 Aug 2024 10:24:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149459; cv=none; b=RrXwNnyGwAnm1drC4RXeQkKjjHPhaAdyfYU7LTFszZlnDg4ETrs5tsJJwABAF3x7Gnko61MYNH+kH0Oy/eZdBgbQKTtPeOpEX80bHCNDvcVXo7qI0G5MFdkNWYQ+YFLhJzXntWKnRZ3r14kBxFXugnXZJAWcR8XnM6he/Je0S1Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149459; c=relaxed/simple; bh=zQjO5mrTLA4zDxzIFqWyoNqm2e4W3q/f1KoIMIJKXsA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AGnlGkX7O/TEsj0Tk+YRimBOni6xoDIHHFaKlccqdFuHinQnsYaa6cFDiGyOqC9pahHbdPxqXNVNEHflzFnkNUOQbPAxgZxlRxwPMM6HQJ/zWe2AAx3M/E1HwcYDQXmTkqpR5hbIbUEQ/DyYFpDqeKwcWHPtTDazKr/1iuVFw6k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=XdBo59jH; arc=none smtp.client-ip=209.85.215.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XdBo59jH" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-7a18ba4143bso3377403a12.2 for ; Tue, 20 Aug 2024 03:24:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724149457; x=1724754257; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=warxYpLVL1xS3Y+iAMmtksOB4vnFBm+hCt/Nma9H8IY=; b=XdBo59jHfag0pYhnuWwIGksOxk1+cim7WNQ7j+ocX8uBynyxOiOzEXxooSvuvXn+Fk hdqpKogZJc342Qtc94GdCteKevOzdiw5dEG1V6mRggNhVmQvKTUOSnk7quJnPiWBwnPe DF/TqlFLL4H1kpx5TTzaVE8o98owEX7/UQz28ayJw9VjyoonDIDx22yMec6QncJenq6q gNdFNJwe0ByvvhCTH+1ty/R95IPCbw7YElMAhyNdkPmQJLOGRZ2p3aoJ9dOdGpzrt2Nj D3qusWZINxgj/Oa2g5b2cMP+u1j5DlU8lfkn4U0LA7tv14cfVBRgyJG+LbIlWucd0c+s JeyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724149457; x=1724754257; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=warxYpLVL1xS3Y+iAMmtksOB4vnFBm+hCt/Nma9H8IY=; b=ZaLUbmKhOXMM0Vq5+Hr8EoCtcmB94RMqeecpqv1gL1QSqzAY2yjamCYVgiK6H3ALP7 rcCMSv4DuTtiOm75Sl10dCXakRQ6PgPv55v24xZDhSvr/0U3hZr1LXM/bFXLBxeLTjs7 StWenM2HmWFOr81ycjiZSI8DMPpvHd9uo+YtjS+NvilqNkQKjy4cN5Pva4rdwrveemLc y+OARXQqfCEfmJjS+sTJrvUwsa26SOFJubuEzMCA8bKbDrU2ZVQZO7u/lrgCo4m4ZIgQ deO+FA/nHwIFQMytKdhzgnzJAyqNYFQaMy7R3z4/I6iYNerzMmL/n8pOITSzXZmkHJYN DAIA== X-Gm-Message-State: AOJu0Yw+Z/7B0ZCDIj9ZHQ/nEbt63Q7qvMb9T9oiM0Iz3pK7S30dOeS9 YF9z4BRzqdJpHtVN96WNxI/1kHz1vfCAnrrEE3WSH7d2uYLEMGkSqr4GdaK6 X-Google-Smtp-Source: AGHT+IGIBShOAMQV9C855+a4U0BUleTPKZfv+vmRuwGrtlDP0KYlvGm1I2yioZslLQiHPnwQV3Z4lw== X-Received: by 2002:a17:90a:5d05:b0:2c9:5c67:dd9e with SMTP id 98e67ed59e1d1-2d3dfd8848amr11688240a91.19.1724149456944; Tue, 20 Aug 2024 03:24:16 -0700 (PDT) Received: from honey-badger.. ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d3e3174bfdsm8976166a91.27.2024.08.20.03.24.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Aug 2024 03:24:16 -0700 (PDT) From: Eduard Zingerman To: bpf@vger.kernel.org, ast@kernel.org Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, kernel-team@fb.com, yonghong.song@linux.dev, hffilwlqm@gmail.com, Eduard Zingerman Subject: [PATCH bpf-next v3 5/8] selftests/bpf: utility function to get program disassembly after jit Date: Tue, 20 Aug 2024 03:23:53 -0700 Message-ID: <20240820102357.3372779-6-eddyz87@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240820102357.3372779-1-eddyz87@gmail.com> References: <20240820102357.3372779-1-eddyz87@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net This commit adds a utility function to get disassembled text for jited representation of a BPF program designated by file descriptor. Function prototype looks as follows: int get_jited_program_text(int fd, char *text, size_t text_sz) Where 'fd' is a file descriptor for the program, 'text' and 'text_sz' refer to a destination buffer for disassembled text. Output format looks as follows: 18: 77 06 ja L0 1a: 50 pushq %rax 1b: 48 89 e0 movq %rsp, %rax 1e: eb 01 jmp L1 20: 50 L0: pushq %rax 21: 50 L1: pushq %rax ^ ^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^ | binary insn | textual insn | representation | representation | | instruction offset inferred local label name The code and makefile changes are inspired by jit_disasm.c from bpftool. Use llvm libraries to disassemble BPF program instead of libbfd to avoid issues with disassembly output stability pointed out in [1]. Selftests makefile uses Makefile.feature to detect if LLVM libraries are available. If that is not the case selftests build proceeds but the function returns -EOPNOTSUPP at runtime. [1] commit eb9d1acf634b ("bpftool: Add LLVM as default library for disassembling JIT-ed programs") Acked-by: Yonghong Song Signed-off-by: Eduard Zingerman --- tools/testing/selftests/bpf/.gitignore | 1 + tools/testing/selftests/bpf/Makefile | 48 +++- .../selftests/bpf/jit_disasm_helpers.c | 234 ++++++++++++++++++ .../selftests/bpf/jit_disasm_helpers.h | 10 + 4 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/bpf/jit_disasm_helpers.c create mode 100644 tools/testing/selftests/bpf/jit_disasm_helpers.h diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore index 8f14d8faeb0b..7de4108771a0 100644 --- a/tools/testing/selftests/bpf/.gitignore +++ b/tools/testing/selftests/bpf/.gitignore @@ -8,6 +8,7 @@ test_lru_map test_lpm_map test_tag FEATURE-DUMP.libbpf +FEATURE-DUMP.selftests fixdep /test_progs /test_progs-no_alu32 diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index f54185e96a95..5ec3b543c732 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -33,6 +33,13 @@ OPT_FLAGS ?= $(if $(RELEASE),-O2,-O0) LIBELF_CFLAGS := $(shell $(PKG_CONFIG) libelf --cflags 2>/dev/null) LIBELF_LIBS := $(shell $(PKG_CONFIG) libelf --libs 2>/dev/null || echo -lelf) +ifeq ($(srctree),) +srctree := $(patsubst %/,%,$(dir $(CURDIR))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +srctree := $(patsubst %/,%,$(dir $(srctree))) +endif + CFLAGS += -g $(OPT_FLAGS) -rdynamic \ -Wall -Werror -fno-omit-frame-pointer \ $(GENFLAGS) $(SAN_CFLAGS) $(LIBELF_CFLAGS) \ @@ -55,6 +62,9 @@ progs/test_sk_lookup.c-CFLAGS := -fno-strict-aliasing progs/timer_crash.c-CFLAGS := -fno-strict-aliasing progs/test_global_func9.c-CFLAGS := -fno-strict-aliasing +# Some utility functions use LLVM libraries +jit_disasm_helpers.c-CFLAGS = $(LLVM_CFLAGS) + ifneq ($(LLVM),) # Silence some warnings when compiled with clang CFLAGS += -Wno-unused-command-line-argument @@ -164,6 +174,31 @@ endef include ../lib.mk +NON_CHECK_FEAT_TARGETS := clean docs-clean +CHECK_FEAT := $(filter-out $(NON_CHECK_FEAT_TARGETS),$(or $(MAKECMDGOALS), "none")) +ifneq ($(CHECK_FEAT),) +FEATURE_USER := .selftests +FEATURE_TESTS := llvm +FEATURE_DISPLAY := $(FEATURE_TESTS) + +# Makefile.feature expects OUTPUT to end with a slash +$(let OUTPUT,$(OUTPUT)/,\ + $(eval include ../../../build/Makefile.feature)) +endif + +ifeq ($(feature-llvm),1) + LLVM_CFLAGS += -DHAVE_LLVM_SUPPORT + LLVM_CONFIG_LIB_COMPONENTS := mcdisassembler all-targets + # both llvm-config and lib.mk add -D_GNU_SOURCE, which ends up as conflict + LLVM_CFLAGS += $(filter-out -D_GNU_SOURCE,$(shell $(LLVM_CONFIG) --cflags)) + LLVM_LDLIBS += $(shell $(LLVM_CONFIG) --libs $(LLVM_CONFIG_LIB_COMPONENTS)) + ifeq ($(shell $(LLVM_CONFIG) --shared-mode),static) + LLVM_LDLIBS += $(shell $(LLVM_CONFIG) --system-libs $(LLVM_CONFIG_LIB_COMPONENTS)) + LLVM_LDLIBS += -lstdc++ + endif + LLVM_LDFLAGS += $(shell $(LLVM_CONFIG) --ldflags) +endif + SCRATCH_DIR := $(OUTPUT)/tools BUILD_DIR := $(SCRATCH_DIR)/build INCLUDE_DIR := $(SCRATCH_DIR)/include @@ -611,6 +646,10 @@ ifeq ($(filter clean docs-clean,$(MAKECMDGOALS)),) include $(wildcard $(TRUNNER_TEST_OBJS:.o=.d)) endif +# add per extra obj CFGLAGS definitions +$(foreach N,$(patsubst $(TRUNNER_OUTPUT)/%.o,%,$(TRUNNER_EXTRA_OBJS)), \ + $(eval $(TRUNNER_OUTPUT)/$(N).o: CFLAGS += $($(N).c-CFLAGS))) + $(TRUNNER_EXTRA_OBJS): $(TRUNNER_OUTPUT)/%.o: \ %.c \ $(TRUNNER_EXTRA_HDRS) \ @@ -627,6 +666,9 @@ ifneq ($2:$(OUTPUT),:$(shell pwd)) $(Q)rsync -aq $$^ $(TRUNNER_OUTPUT)/ endif +$(OUTPUT)/$(TRUNNER_BINARY): LDLIBS += $$(LLVM_LDLIBS) +$(OUTPUT)/$(TRUNNER_BINARY): LDFLAGS += $$(LLVM_LDFLAGS) + # some X.test.o files have runtime dependencies on Y.bpf.o files $(OUTPUT)/$(TRUNNER_BINARY): | $(TRUNNER_BPF_OBJS) @@ -636,7 +678,7 @@ $(OUTPUT)/$(TRUNNER_BINARY): $(TRUNNER_TEST_OBJS) \ $(TRUNNER_BPFTOOL) \ | $(TRUNNER_BINARY)-extras $$(call msg,BINARY,,$$@) - $(Q)$$(CC) $$(CFLAGS) $$(filter %.a %.o,$$^) $$(LDLIBS) -o $$@ + $(Q)$$(CC) $$(CFLAGS) $$(filter %.a %.o,$$^) $$(LDLIBS) $$(LDFLAGS) -o $$@ $(Q)$(RESOLVE_BTFIDS) --btf $(TRUNNER_OUTPUT)/btf_data.bpf.o $$@ $(Q)ln -sf $(if $2,..,.)/tools/build/bpftool/$(USE_BOOTSTRAP)bpftool \ $(OUTPUT)/$(if $2,$2/)bpftool @@ -655,6 +697,7 @@ TRUNNER_EXTRA_SOURCES := test_progs.c \ cap_helpers.c \ unpriv_helpers.c \ netlink_helpers.c \ + jit_disasm_helpers.c \ test_loader.c \ xsk.c \ disasm.c \ @@ -797,7 +840,8 @@ EXTRA_CLEAN := $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ $(addprefix $(OUTPUT)/,*.o *.d *.skel.h *.lskel.h *.subskel.h \ no_alu32 cpuv4 bpf_gcc bpf_testmod.ko \ bpf_test_no_cfi.ko \ - liburandom_read.so) + liburandom_read.so) \ + $(OUTPUT)/FEATURE-DUMP.selftests .PHONY: docs docs-clean diff --git a/tools/testing/selftests/bpf/jit_disasm_helpers.c b/tools/testing/selftests/bpf/jit_disasm_helpers.c new file mode 100644 index 000000000000..1b0f1fd267c0 --- /dev/null +++ b/tools/testing/selftests/bpf/jit_disasm_helpers.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +#include +#include +#include + +#ifdef HAVE_LLVM_SUPPORT + +#include +#include +#include +#include + +/* The intent is to use get_jited_program_text() for small test + * programs written in BPF assembly, thus assume that 32 local labels + * would be sufficient. + */ +#define MAX_LOCAL_LABELS 32 + +static bool llvm_initialized; + +struct local_labels { + bool print_phase; + __u32 prog_len; + __u32 cnt; + __u32 pcs[MAX_LOCAL_LABELS]; + char names[MAX_LOCAL_LABELS][4]; +}; + +static const char *lookup_symbol(void *data, uint64_t ref_value, uint64_t *ref_type, + uint64_t ref_pc, const char **ref_name) +{ + struct local_labels *labels = data; + uint64_t type = *ref_type; + int i; + + *ref_type = LLVMDisassembler_ReferenceType_InOut_None; + *ref_name = NULL; + if (type != LLVMDisassembler_ReferenceType_In_Branch) + return NULL; + /* Depending on labels->print_phase either discover local labels or + * return a name assigned with local jump target: + * - if print_phase is true and ref_value is in labels->pcs, + * return corresponding labels->name. + * - if print_phase is false, save program-local jump targets + * in labels->pcs; + */ + if (labels->print_phase) { + for (i = 0; i < labels->cnt; ++i) + if (labels->pcs[i] == ref_value) + return labels->names[i]; + } else { + if (labels->cnt < MAX_LOCAL_LABELS && ref_value < labels->prog_len) + labels->pcs[labels->cnt++] = ref_value; + } + return NULL; +} + +static int disasm_insn(LLVMDisasmContextRef ctx, uint8_t *image, __u32 len, __u32 pc, + char *buf, __u32 buf_sz) +{ + int i, cnt; + + cnt = LLVMDisasmInstruction(ctx, image + pc, len - pc, pc, + buf, buf_sz); + if (cnt > 0) + return cnt; + PRINT_FAIL("Can't disasm instruction at offset %d:", pc); + for (i = 0; i < 16 && pc + i < len; ++i) + printf(" %02x", image[pc + i]); + printf("\n"); + return -EINVAL; +} + +static int cmp_u32(const void *_a, const void *_b) +{ + __u32 a = *(__u32 *)_a; + __u32 b = *(__u32 *)_b; + + if (a < b) + return -1; + if (a > b) + return 1; + return 0; +} + +static int disasm_one_func(FILE *text_out, uint8_t *image, __u32 len) +{ + char *label, *colon, *triple = NULL; + LLVMDisasmContextRef ctx = NULL; + struct local_labels labels = {}; + __u32 *label_pc, pc; + int i, cnt, err = 0; + char buf[64]; + + triple = LLVMGetDefaultTargetTriple(); + ctx = LLVMCreateDisasm(triple, &labels, 0, NULL, lookup_symbol); + if (!ASSERT_OK_PTR(ctx, "LLVMCreateDisasm")) { + err = -EINVAL; + goto out; + } + + cnt = LLVMSetDisasmOptions(ctx, LLVMDisassembler_Option_PrintImmHex); + if (!ASSERT_EQ(cnt, 1, "LLVMSetDisasmOptions")) { + err = -EINVAL; + goto out; + } + + /* discover labels */ + labels.prog_len = len; + pc = 0; + while (pc < len) { + cnt = disasm_insn(ctx, image, len, pc, buf, 1); + if (cnt < 0) { + err = cnt; + goto out; + } + pc += cnt; + } + qsort(labels.pcs, labels.cnt, sizeof(*labels.pcs), cmp_u32); + for (i = 0; i < labels.cnt; ++i) + /* use (i % 100) to avoid format truncation warning */ + snprintf(labels.names[i], sizeof(labels.names[i]), "L%d", i % 100); + + /* now print with labels */ + labels.print_phase = true; + pc = 0; + while (pc < len) { + cnt = disasm_insn(ctx, image, len, pc, buf, sizeof(buf)); + if (cnt < 0) { + err = cnt; + goto out; + } + label_pc = bsearch(&pc, labels.pcs, labels.cnt, sizeof(*labels.pcs), cmp_u32); + label = ""; + colon = ""; + if (label_pc) { + label = labels.names[label_pc - labels.pcs]; + colon = ":"; + } + fprintf(text_out, "%x:\t", pc); + for (i = 0; i < cnt; ++i) + fprintf(text_out, "%02x ", image[pc + i]); + for (i = cnt * 3; i < 12 * 3; ++i) + fputc(' ', text_out); + fprintf(text_out, "%s%s%s\n", label, colon, buf); + pc += cnt; + } + +out: + if (triple) + LLVMDisposeMessage(triple); + if (ctx) + LLVMDisasmDispose(ctx); + return err; +} + +int get_jited_program_text(int fd, char *text, size_t text_sz) +{ + struct bpf_prog_info info = {}; + __u32 info_len = sizeof(info); + __u32 jited_funcs, len, pc; + __u32 *func_lens = NULL; + FILE *text_out = NULL; + uint8_t *image = NULL; + int i, err = 0; + + if (!llvm_initialized) { + LLVMInitializeAllTargetInfos(); + LLVMInitializeAllTargetMCs(); + LLVMInitializeAllDisassemblers(); + llvm_initialized = 1; + } + + text_out = fmemopen(text, text_sz, "w"); + if (!ASSERT_OK_PTR(text_out, "open_memstream")) { + err = -errno; + goto out; + } + + /* first call is to find out jited program len */ + err = bpf_prog_get_info_by_fd(fd, &info, &info_len); + if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd #1")) + goto out; + + len = info.jited_prog_len; + image = malloc(len); + if (!ASSERT_OK_PTR(image, "malloc(info.jited_prog_len)")) { + err = -ENOMEM; + goto out; + } + + jited_funcs = info.nr_jited_func_lens; + func_lens = malloc(jited_funcs * sizeof(__u32)); + if (!ASSERT_OK_PTR(func_lens, "malloc(info.nr_jited_func_lens)")) { + err = -ENOMEM; + goto out; + } + + memset(&info, 0, sizeof(info)); + info.jited_prog_insns = (__u64)image; + info.jited_prog_len = len; + info.jited_func_lens = (__u64)func_lens; + info.nr_jited_func_lens = jited_funcs; + err = bpf_prog_get_info_by_fd(fd, &info, &info_len); + if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd #2")) + goto out; + + for (pc = 0, i = 0; i < jited_funcs; ++i) { + fprintf(text_out, "func #%d:\n", i); + disasm_one_func(text_out, image + pc, func_lens[i]); + fprintf(text_out, "\n"); + pc += func_lens[i]; + } + +out: + if (text_out) + fclose(text_out); + if (image) + free(image); + if (func_lens) + free(func_lens); + return err; +} + +#else /* HAVE_LLVM_SUPPORT */ + +int get_jited_program_text(int fd, char *text, size_t text_sz) +{ + if (env.verbosity >= VERBOSE_VERY) + printf("compiled w/o llvm development libraries, can't dis-assembly binary code"); + return -EOPNOTSUPP; +} + +#endif /* HAVE_LLVM_SUPPORT */ diff --git a/tools/testing/selftests/bpf/jit_disasm_helpers.h b/tools/testing/selftests/bpf/jit_disasm_helpers.h new file mode 100644 index 000000000000..e6924fd65ecf --- /dev/null +++ b/tools/testing/selftests/bpf/jit_disasm_helpers.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ + +#ifndef __JIT_DISASM_HELPERS_H +#define __JIT_DISASM_HELPERS_H + +#include + +int get_jited_program_text(int fd, char *text, size_t text_sz); + +#endif /* __JIT_DISASM_HELPERS_H */ From patchwork Tue Aug 20 10:23:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduard Zingerman X-Patchwork-Id: 13769862 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-pg1-f172.google.com (mail-pg1-f172.google.com [209.85.215.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4793E18E75A for ; Tue, 20 Aug 2024 10:24:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149461; cv=none; b=B3q48LL3gloB8ZvuesbHdA5WKD04LsIXPAfc3W9iWo6Uy+4z00Z/crK/rXq0GIqiFpARjNAQ6LDht/5XYQpxLr9ku9jHElMUBXzZwSfSrTgx6GxUOT3mBKuKJLo+9Z9QDacmQ3VvHSMS05KYCXMH72D1JkxyNqk7z2DBX8fkKlA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149461; c=relaxed/simple; bh=xZlgOuNnxg5f5PtTcqSql3S4mmieuH2eyfgKm9j6AuA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DfHngbOwhE6zSoIcDbqhXnjJ1811wFl8kPXspo3ru0NE/unmPkJqRMvLrmoI8o5yj7IJnrORWuN8y0NjAMF0YBOUAqfQ3+CfOeoN5cSdjaHIVpZO1GHHy9SInKdRjAp2mFtj8DBlf2MFUBfGo10lkWN9CwFijDg0+Ni9eUH/wFY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Fydh+fmG; arc=none smtp.client-ip=209.85.215.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Fydh+fmG" Received: by mail-pg1-f172.google.com with SMTP id 41be03b00d2f7-6c5bcb8e8edso3862450a12.2 for ; Tue, 20 Aug 2024 03:24:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724149458; x=1724754258; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3I587T14MUg+cH3UjNZ+l/VjKeN+yqEGyZSe5s22Tik=; b=Fydh+fmG/XnMyr2WD0EFLV2C+CL+nJlVTYLoap9q5LxPE3fKE+f7eNrQ9/XmdrFb4b V9GSWYBTKP72dpklMhWuTvRrJxzJuxFwanmjbkZfOTduSNjF2Ioy550D2QFam8AxY0cH stJ/f9K7Lpx/8cijseNENkai4CJuPZAJJF66tjsT/V18LEP+KfMrFu0FvzsCN5x490f4 b7Anq91xbZS82ySybJ/Q9MUkF3hWl4FRmjIXJv+bFHCd8tr0xW1j2Dj427gWWSZGpETR KFdHUImPdiSbXHkPHxYMoczbBiD04386HIFhZi+KbIP2cxRxEPVxQx0itRLAbA7fvPFW g0RA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724149458; x=1724754258; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3I587T14MUg+cH3UjNZ+l/VjKeN+yqEGyZSe5s22Tik=; b=GzGL2fvCth7eyx2lkD+8bh2fRtdXamETt6WKcJT+7Z7+xyCRFZ0QbzqEizIzmcA+Zc 4bkL9YmEFWpTsu9KkkDgJLtxJtdDTouZPFfapLVvk4XiPBPrbmI4qLcDBn5x4YL1cL8n /vPjOTIdJ9Sr8ND+r6ql2wSj3f8uy17+GNH2WHFgJRBucYiqQrpYFKq9Ip6VakuqOC/X keio+zjr3+3645TkFA+JF1N4dbxAQ/2qnI5IHsVMr3k8bapQxWoVfSt4IgUmmeJaOrls uWDi6IEQaLraczcOEmw3VkA4ICM6ifuAweyZrp4cMMa6BD9f9bzCmLua88XeNBfNS/16 RLwA== X-Gm-Message-State: AOJu0YxICnfwjnhCrdVi6JEybJsJjzrjdNFt9+ci/wiN0uIzsAI5ur4z kEaqeUWsFtQahjrjFzIN/1MxX91YsxqrU15kmGePIe3gdJzXAiDBIKRYVpI9 X-Google-Smtp-Source: AGHT+IHLV8xuQNstegMR9CbWuoz/Ptrg3wSz2umamZBbLQVBx7fd/OmIlEr6OBg+VSAjCCYiTKaL5A== X-Received: by 2002:a17:90a:ca89:b0:2c9:754d:2cba with SMTP id 98e67ed59e1d1-2d3dfc2aa3amr15483959a91.3.1724149458170; Tue, 20 Aug 2024 03:24:18 -0700 (PDT) Received: from honey-badger.. ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d3e3174bfdsm8976166a91.27.2024.08.20.03.24.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Aug 2024 03:24:17 -0700 (PDT) From: Eduard Zingerman To: bpf@vger.kernel.org, ast@kernel.org Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, kernel-team@fb.com, yonghong.song@linux.dev, hffilwlqm@gmail.com, Eduard Zingerman Subject: [PATCH bpf-next v3 6/8] selftests/bpf: __jited test tag to check disassembly after jit Date: Tue, 20 Aug 2024 03:23:54 -0700 Message-ID: <20240820102357.3372779-7-eddyz87@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240820102357.3372779-1-eddyz87@gmail.com> References: <20240820102357.3372779-1-eddyz87@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Allow to verify jit behaviour by writing tests as below: SEC("tp") __arch_x86_64 __jited(" endbr64") __jited(" nopl (%rax,%rax)") __jited(" xorq %rax, %rax") ... __naked void some_test(void) { asm volatile (... ::: __clobber_all); } Allow regular expressions in patterns, same way as in __msg. By default assume that each __jited pattern has to be matched on the next consecutive line of the disassembly, e.g.: __jited(" endbr64") # matched on line N __jited(" nopl (%rax,%rax)") # matched on line N+1 If match occurs on a wrong line an error is reported. To override this behaviour use __jited("..."), e.g.: __jited(" endbr64") # matched on line N __jited("...") # not matched __jited(" nopl (%rax,%rax)") # matched on any line >= N Signed-off-by: Eduard Zingerman --- tools/testing/selftests/bpf/progs/bpf_misc.h | 35 +++++ tools/testing/selftests/bpf/test_loader.c | 149 ++++++++++++++++--- 2 files changed, 161 insertions(+), 23 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h index cc3ef20a6490..eccaf955e394 100644 --- a/tools/testing/selftests/bpf/progs/bpf_misc.h +++ b/tools/testing/selftests/bpf/progs/bpf_misc.h @@ -36,6 +36,39 @@ * Regular expressions could be specified same way as in __msg. * __xlated_unpriv Same as __xlated but for unprivileged mode. * + * __jited Match a line in a disassembly of the jited BPF program. + * Has to be used after __arch_* macro. + * For example: + * + * __arch_x86_64 + * __jited(" endbr64") + * __jited(" nopl (%rax,%rax)") + * __jited(" xorq %rax, %rax") + * ... + * __naked void some_test(void) + * { + * asm volatile (... ::: __clobber_all); + * } + * + * Regular expressions could be included in patterns same way + * as in __msg. + * + * By default assume that each pattern has to be matched on the + * next consecutive line of disassembly, e.g.: + * + * __jited(" endbr64") # matched on line N + * __jited(" nopl (%rax,%rax)") # matched on line N+1 + * + * If match occurs on a wrong line an error is reported. + * To override this behaviour use literal "...", e.g.: + * + * __jited(" endbr64") # matched on line N + * __jited("...") # not matched + * __jited(" nopl (%rax,%rax)") # matched on any line >= N + * + * __jited_unpriv Same as __jited but for unprivileged mode. + * + * * __success Expect program load success in privileged mode. * __success_unpriv Expect program load success in unprivileged mode. * @@ -76,11 +109,13 @@ */ #define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" XSTR(__COUNTER__) "=" msg))) #define __xlated(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated=" XSTR(__COUNTER__) "=" msg))) +#define __jited(msg) __attribute__((btf_decl_tag("comment:test_jited=" XSTR(__COUNTER__) "=" msg))) #define __failure __attribute__((btf_decl_tag("comment:test_expect_failure"))) #define __success __attribute__((btf_decl_tag("comment:test_expect_success"))) #define __description(desc) __attribute__((btf_decl_tag("comment:test_description=" desc))) #define __msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" XSTR(__COUNTER__) "=" msg))) #define __xlated_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" XSTR(__COUNTER__) "=" msg))) +#define __jited_unpriv(msg) __attribute__((btf_decl_tag("comment:test_jited=" XSTR(__COUNTER__) "=" msg))) #define __failure_unpriv __attribute__((btf_decl_tag("comment:test_expect_failure_unpriv"))) #define __success_unpriv __attribute__((btf_decl_tag("comment:test_expect_success_unpriv"))) #define __log_level(lvl) __attribute__((btf_decl_tag("comment:test_log_level="#lvl))) diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c index b0d7158e00c1..d588c612ac03 100644 --- a/tools/testing/selftests/bpf/test_loader.c +++ b/tools/testing/selftests/bpf/test_loader.c @@ -10,6 +10,7 @@ #include "disasm_helpers.h" #include "unpriv_helpers.h" #include "cap_helpers.h" +#include "jit_disasm_helpers.h" #define str_has_pfx(str, pfx) \ (strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0) @@ -33,6 +34,8 @@ #define TEST_TAG_AUXILIARY_UNPRIV "comment:test_auxiliary_unpriv" #define TEST_BTF_PATH "comment:test_btf_path=" #define TEST_TAG_ARCH "comment:test_arch=" +#define TEST_TAG_JITED_PFX "comment:test_jited=" +#define TEST_TAG_JITED_PFX_UNPRIV "comment:test_jited_unpriv=" /* Warning: duplicated in bpf_misc.h */ #define POINTER_VALUE 0xcafe4all @@ -68,6 +71,7 @@ struct test_subspec { bool expect_failure; struct expected_msgs expect_msgs; struct expected_msgs expect_xlated; + struct expected_msgs jited; int retval; bool execute; }; @@ -124,6 +128,8 @@ static void free_test_spec(struct test_spec *spec) free_msgs(&spec->unpriv.expect_msgs); free_msgs(&spec->priv.expect_xlated); free_msgs(&spec->unpriv.expect_xlated); + free_msgs(&spec->priv.jited); + free_msgs(&spec->unpriv.jited); free(spec->priv.name); free(spec->unpriv.name); @@ -237,6 +243,21 @@ static int push_msg(const char *substr, struct expected_msgs *msgs) return __push_msg(substr, false, msgs); } +static int push_disasm_msg(const char *regex_str, bool *on_next_line, struct expected_msgs *msgs) +{ + int err; + + if (strcmp(regex_str, "...") == 0) { + *on_next_line = false; + return 0; + } + err = __push_msg(regex_str, *on_next_line, msgs); + if (err) + return err; + *on_next_line = true; + return 0; +} + static int parse_int(const char *str, int *val, const char *name) { char *end; @@ -320,6 +341,18 @@ enum arch { ARCH_RISCV64 = 0x4, }; +static int get_current_arch(void) +{ +#if defined(__x86_64__) + return ARCH_X86_64; +#elif defined(__aarch64__) + return ARCH_ARM64; +#elif defined(__riscv) && __riscv_xlen == 64 + return ARCH_RISCV64; +#endif + return 0; +} + /* Uses btf_decl_tag attributes to describe the expected test * behavior, see bpf_misc.h for detailed description of each attribute * and attribute combinations. @@ -332,9 +365,13 @@ static int parse_test_spec(struct test_loader *tester, const char *description = NULL; bool has_unpriv_result = false; bool has_unpriv_retval = false; + bool unpriv_jit_on_next_line; + bool jit_on_next_line; + bool collect_jit = false; int func_id, i, err = 0; u32 arch_mask = 0; struct btf *btf; + enum arch arch; memset(spec, 0, sizeof(*spec)); @@ -399,6 +436,30 @@ static int parse_test_spec(struct test_loader *tester, if (err) goto cleanup; spec->mode_mask |= UNPRIV; + } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_JITED_PFX))) { + if (arch_mask == 0) { + PRINT_FAIL("__jited used before __arch_*"); + goto cleanup; + } + if (collect_jit) { + err = push_disasm_msg(msg, &jit_on_next_line, + &spec->priv.jited); + if (err) + goto cleanup; + spec->mode_mask |= PRIV; + } + } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_JITED_PFX_UNPRIV))) { + if (arch_mask == 0) { + PRINT_FAIL("__unpriv_jited used before __arch_*"); + goto cleanup; + } + if (collect_jit) { + err = push_disasm_msg(msg, &unpriv_jit_on_next_line, + &spec->unpriv.jited); + if (err) + goto cleanup; + spec->mode_mask |= UNPRIV; + } } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX))) { err = push_msg(msg, &spec->priv.expect_xlated); if (err) @@ -459,16 +520,20 @@ static int parse_test_spec(struct test_loader *tester, } else if (str_has_pfx(s, TEST_TAG_ARCH)) { val = s + sizeof(TEST_TAG_ARCH) - 1; if (strcmp(val, "X86_64") == 0) { - arch_mask |= ARCH_X86_64; + arch = ARCH_X86_64; } else if (strcmp(val, "ARM64") == 0) { - arch_mask |= ARCH_ARM64; + arch = ARCH_ARM64; } else if (strcmp(val, "RISCV64") == 0) { - arch_mask |= ARCH_RISCV64; + arch = ARCH_RISCV64; } else { PRINT_FAIL("bad arch spec: '%s'", val); err = -EINVAL; goto cleanup; } + arch_mask |= arch; + collect_jit = get_current_arch() == arch; + unpriv_jit_on_next_line = true; + jit_on_next_line = true; } else if (str_has_pfx(s, TEST_BTF_PATH)) { spec->btf_custom_path = s + sizeof(TEST_BTF_PATH) - 1; } @@ -521,6 +586,8 @@ static int parse_test_spec(struct test_loader *tester, clone_msgs(&spec->priv.expect_msgs, &spec->unpriv.expect_msgs); if (spec->unpriv.expect_xlated.cnt == 0) clone_msgs(&spec->priv.expect_xlated, &spec->unpriv.expect_xlated); + if (spec->unpriv.jited.cnt == 0) + clone_msgs(&spec->priv.jited, &spec->unpriv.jited); } spec->valid = true; @@ -575,16 +642,29 @@ static void emit_xlated(const char *xlated, bool force) fprintf(stdout, "XLATED:\n=============\n%s=============\n", xlated); } +static void emit_jited(const char *jited, bool force) +{ + if (!force && env.verbosity == VERBOSE_NONE) + return; + fprintf(stdout, "JITED:\n=============\n%s=============\n", jited); +} + static void validate_msgs(char *log_buf, struct expected_msgs *msgs, void (*emit_fn)(const char *buf, bool force)) { + const char *log = log_buf, *prev_match; regmatch_t reg_match[1]; - const char *log = log_buf; + int prev_match_line; + int match_line; int i, j, err; + prev_match_line = -1; + match_line = 0; + prev_match = log; for (i = 0; i < msgs->cnt; i++) { struct expect_msg *msg = &msgs->patterns[i]; - const char *match = NULL; + const char *match = NULL, *pat_status; + bool wrong_line = false; if (!msg->is_regex) { match = strstr(log, msg->substr); @@ -598,19 +678,41 @@ static void validate_msgs(char *log_buf, struct expected_msgs *msgs, } } - if (!match) { + if (match) { + for (; prev_match < match; ++prev_match) + if (*prev_match == '\n') + ++match_line; + wrong_line = msg->on_next_line && prev_match_line >= 0 && + prev_match_line + 1 != match_line; + } + + if (!match || wrong_line) { PRINT_FAIL("expect_msg\n"); if (env.verbosity == VERBOSE_NONE) emit_fn(log_buf, true /*force*/); for (j = 0; j <= i; j++) { msg = &msgs->patterns[j]; + if (j < i) + pat_status = "MATCHED "; + else if (wrong_line) + pat_status = "WRONG LINE"; + else + pat_status = "EXPECTED "; + msg = &msgs->patterns[j]; fprintf(stderr, "%s %s: '%s'\n", - j < i ? "MATCHED " : "EXPECTED", + pat_status, msg->is_regex ? " REGEX" : "SUBSTR", msg->substr); } - return; + if (wrong_line) { + fprintf(stderr, + "expecting match at line %d, actual match is at line %d\n", + prev_match_line + 1, match_line); + } + break; } + + prev_match_line = match_line; } } @@ -769,20 +871,6 @@ static int get_xlated_program_text(int prog_fd, char *text, size_t text_sz) return err; } -static bool run_on_current_arch(int arch_mask) -{ - if (arch_mask == 0) - return true; -#if defined(__x86_64__) - return arch_mask & ARCH_X86_64; -#elif defined(__aarch64__) - return arch_mask & ARCH_ARM64; -#elif defined(__riscv) && __riscv_xlen == 64 - return arch_mask & ARCH_RISCV64; -#endif - return false; -} - /* this function is forced noinline and has short generic name to look better * in test_progs output (in case of a failure) */ @@ -807,7 +895,7 @@ void run_subtest(struct test_loader *tester, if (!test__start_subtest(subspec->name)) return; - if (!run_on_current_arch(spec->arch_mask)) { + if ((get_current_arch() & spec->arch_mask) == 0) { test__skip(); return; } @@ -884,6 +972,21 @@ void run_subtest(struct test_loader *tester, validate_msgs(tester->log_buf, &subspec->expect_xlated, emit_xlated); } + if (subspec->jited.cnt) { + err = get_jited_program_text(bpf_program__fd(tprog), + tester->log_buf, tester->log_buf_sz); + if (err == -EOPNOTSUPP) { + printf("%s:SKIP: jited programs disassembly is not supported,\n", __func__); + printf("%s:SKIP: tests are built w/o LLVM development libs\n", __func__); + test__skip(); + goto tobj_cleanup; + } + if (!ASSERT_EQ(err, 0, "get_jited_program_text")) + goto tobj_cleanup; + emit_jited(tester->log_buf, false /*force*/); + validate_msgs(tester->log_buf, &subspec->jited, emit_jited); + } + if (should_do_test_run(spec, subspec)) { /* For some reason test_verifier executes programs * with all capabilities restored. Do the same here. From patchwork Tue Aug 20 10:23:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduard Zingerman X-Patchwork-Id: 13769864 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8074A18FC79 for ; Tue, 20 Aug 2024 10:24:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149463; cv=none; b=bUnXKyzu1Z91efbcqBSY+tbbGjZhOMyG4gi2aiOg9pK7Hvcb70DhTbmrsi+S3ZO2D3LAt0pFjIEfdWjyw7RK4DtH3lUECwlnylCLX2nmNnDNwdv0i+rHDCtsp6/pcR/xt0K/DEJ6izJvR/M6Ldz4YIH7dytDYwt/hRsPLW1a4Hk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149463; c=relaxed/simple; bh=MOwEd5WaTuidL1At3Q85rfKIgf1ZvTMqBh/FpL19+d0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=g5smIrk8hDUZH31YPGPydGU8eaMyNHGSWepVDvYpin+aadyJB/CnI/iPVVUdmisvDdT31o7ePnep6zzxGyLVnq33+bWeH9xm31TtkEje6YOB+9s1Zh18jqlBjCbct+guk5MPZ3/nwjLn+QsWQymtc+NyXsBxnkFwR7w4svmFpzI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kxsiaUG1; arc=none smtp.client-ip=209.85.216.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kxsiaUG1" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-2d1daa2577bso4043714a91.2 for ; Tue, 20 Aug 2024 03:24:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724149461; x=1724754261; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=XF6LED9hCLCc1TGB+X4DY2KX7XE1HShy+5rzy1zSX5Y=; b=kxsiaUG1xISpOHtseXolGluLpt4SrqHRPPcBXh2oyIfeMGpxtO+7VL6V4zJYUBcOAL s5GHI9GHO+otZlP4fWNM2C7n0QkHsAzybwzDx4l0bAk1muuCqzY311LA5f/7tpbz2eZl AtkJRX7NTVit1+4luGDdpm1zrX2p4cBwWjOEDGAj0d317ORmD0AN9MtMP4Nr7z6pbCdi DidpViNSkoFpPKIJvzbvSfMXPvb+h94Sx9mgRXQS5rm2XUkOtbPzWaPA143MKlsmFtq9 4BuyQMJpMSBL3BHst759gQkLWaI85IJsXcmCblLZadFBF2FlJ7zqLN4gacj6Q8rwFHEe hC6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724149461; x=1724754261; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=XF6LED9hCLCc1TGB+X4DY2KX7XE1HShy+5rzy1zSX5Y=; b=YCfHV30cs25nvi4rTKBMA76qcta51C+k3kUGOUaScgWZ2WPKcFsF2MESpBUGSKe1t2 diUT1QYqXGnr9lKzyeb0ZL4GRvDQPQoIn90JfiDWtGaM+RRpaQo3QFPtm2Q0Ca8qURtQ J6tdWu00Lb5lUkQn+TKlaIlgD9rcrbE6qMveaNG0ARSHxx8yQMzlyvw2zVPY7JxAu/Yr td1Rpm2Z5onJ9CMQUnU/2uxbLW2JvDgFNbS0mWdnyDsxWkEZfjsuCtavm4up9poxIDbH sYOeC7dDILO1SepSROlra88ekxLTZM+6H/GfLQPQmXd/juPetkboku9K3Y4XdzwZg0gE 4otQ== X-Gm-Message-State: AOJu0YyXi1AMgTeDFYDZl4Pmwa3UtUgKi2sKTN6gNqwXnrElV3IOFOty gg7t127rmtgig+JiE2vs3YuN9nK+26SBHD94o/Wi3rHXmMR8OhlcxcwAuoIS X-Google-Smtp-Source: AGHT+IHg6U5/DV8tRBrAXQn8+Gz2llJLjGmC9NKkyp3y0gafCkElt3j5fKf0pU5JEz8x2r/9ACy08Q== X-Received: by 2002:a17:90b:70e:b0:2d3:bc5e:8452 with SMTP id 98e67ed59e1d1-2d3e0561f93mr14067733a91.32.1724149460454; Tue, 20 Aug 2024 03:24:20 -0700 (PDT) Received: from honey-badger.. ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d3e3174bfdsm8976166a91.27.2024.08.20.03.24.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Aug 2024 03:24:20 -0700 (PDT) From: Eduard Zingerman To: bpf@vger.kernel.org, ast@kernel.org Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, kernel-team@fb.com, yonghong.song@linux.dev, hffilwlqm@gmail.com, Eduard Zingerman Subject: [PATCH bpf-next v3 7/8] selftests/bpf: validate jit behaviour for tail calls Date: Tue, 20 Aug 2024 03:23:56 -0700 Message-ID: <20240820102357.3372779-9-eddyz87@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240820102357.3372779-1-eddyz87@gmail.com> References: <20240820102357.3372779-1-eddyz87@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net A program calling sub-program which does a tail call. The idea is to verify instructions generated by jit for tail calls: - in program and sub-program prologues; - for subprogram call instruction; - for tail call itself. Signed-off-by: Eduard Zingerman --- .../selftests/bpf/prog_tests/verifier.c | 2 + .../bpf/progs/verifier_tailcall_jit.c | 105 ++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/verifier_tailcall_jit.c diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c index f8f546eba488..cf3662dbd24f 100644 --- a/tools/testing/selftests/bpf/prog_tests/verifier.c +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c @@ -75,6 +75,7 @@ #include "verifier_stack_ptr.skel.h" #include "verifier_subprog_precision.skel.h" #include "verifier_subreg.skel.h" +#include "verifier_tailcall_jit.skel.h" #include "verifier_typedef.skel.h" #include "verifier_uninit.skel.h" #include "verifier_unpriv.skel.h" @@ -198,6 +199,7 @@ void test_verifier_spin_lock(void) { RUN(verifier_spin_lock); } void test_verifier_stack_ptr(void) { RUN(verifier_stack_ptr); } void test_verifier_subprog_precision(void) { RUN(verifier_subprog_precision); } void test_verifier_subreg(void) { RUN(verifier_subreg); } +void test_verifier_tailcall_jit(void) { RUN(verifier_tailcall_jit); } void test_verifier_typedef(void) { RUN(verifier_typedef); } void test_verifier_uninit(void) { RUN(verifier_uninit); } void test_verifier_unpriv(void) { RUN(verifier_unpriv); } diff --git a/tools/testing/selftests/bpf/progs/verifier_tailcall_jit.c b/tools/testing/selftests/bpf/progs/verifier_tailcall_jit.c new file mode 100644 index 000000000000..06d327cf1e1f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/verifier_tailcall_jit.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include "bpf_misc.h" + +int main(void); + +struct { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, 1); + __uint(key_size, sizeof(__u32)); + __array(values, void (void)); +} jmp_table SEC(".maps") = { + .values = { + [0] = (void *) &main, + }, +}; + +__noinline __auxiliary +static __naked int sub(void) +{ + asm volatile ( + "r2 = %[jmp_table] ll;" + "r3 = 0;" + "call 12;" + "exit;" + : + : __imm_addr(jmp_table) + : __clobber_all); +} + +__success +__arch_x86_64 +/* program entry for main(), regular function prologue */ +__jited(" endbr64") +__jited(" nopl (%rax,%rax)") +__jited(" xorq %rax, %rax") +__jited(" pushq %rbp") +__jited(" movq %rsp, %rbp") +/* tail call prologue for program: + * - establish memory location for tail call counter at &rbp[-8]; + * - spill tail_call_cnt_ptr at &rbp[-16]; + * - expect tail call counter to be passed in rax; + * - for entry program rax is a raw counter, value < 33; + * - for tail called program rax is tail_call_cnt_ptr (value > 33). + */ +__jited(" endbr64") +__jited(" cmpq $0x21, %rax") +__jited(" ja L0") +__jited(" pushq %rax") +__jited(" movq %rsp, %rax") +__jited(" jmp L1") +__jited("L0: pushq %rax") /* rbp[-8] = rax */ +__jited("L1: pushq %rax") /* rbp[-16] = rax */ +/* on subprogram call restore rax to be tail_call_cnt_ptr from rbp[-16] + * (cause original rax might be clobbered by this point) + */ +__jited(" movq -0x10(%rbp), %rax") +__jited(" callq 0x{{.*}}") /* call to sub() */ +__jited(" xorl %eax, %eax") +__jited(" leave") +__jited(" retq") +__jited("...") +/* subprogram entry for sub(), regular function prologue */ +__jited(" endbr64") +__jited(" nopl (%rax,%rax)") +__jited(" nopl (%rax)") +__jited(" pushq %rbp") +__jited(" movq %rsp, %rbp") +/* tail call prologue for subprogram address of tail call counter + * stored at rbp[-16]. + */ +__jited(" endbr64") +__jited(" pushq %rax") /* rbp[-8] = rax */ +__jited(" pushq %rax") /* rbp[-16] = rax */ +__jited(" movabsq ${{.*}}, %rsi") /* r2 = &jmp_table */ +__jited(" xorl %edx, %edx") /* r3 = 0 */ +/* bpf_tail_call implementation: + * - load tail_call_cnt_ptr from rbp[-16]; + * - if *tail_call_cnt_ptr < 33, increment it and jump to target; + * - otherwise do nothing. + */ +__jited(" movq -0x10(%rbp), %rax") +__jited(" cmpq $0x21, (%rax)") +__jited(" jae L0") +__jited(" nopl (%rax,%rax)") +__jited(" addq $0x1, (%rax)") /* *tail_call_cnt_ptr += 1 */ +__jited(" popq %rax") +__jited(" popq %rax") +__jited(" jmp {{.*}}") /* jump to tail call tgt */ +__jited("L0: leave") +__jited(" retq") +SEC("tc") +__naked int main(void) +{ + asm volatile ( + "call %[sub];" + "r0 = 0;" + "exit;" + : + : __imm(sub) + : __clobber_all); +} + +char __license[] SEC("license") = "GPL"; From patchwork Tue Aug 20 10:23:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduard Zingerman X-Patchwork-Id: 13769865 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A823318FC7E for ; Tue, 20 Aug 2024 10:24:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149464; cv=none; b=b3/ksF7shPMPZAqSaSbogSjIW/p7xvzlljgOLaEQqmtJuqhlglCKcDNr3FEBiGlEjhCPMekOa5K/I2jOfRjnlf92bY/SyHVNKxWJc2kXh4WvZu2JZ+1jtfTcZrFGVveTYJ1j4pvSis4hf4qLKIGegw3Y2EMnjQcIGmMlOKr8IYA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1724149464; c=relaxed/simple; bh=sBsz/BF4EIAtMVTzSPH2fY/lwM1MNP6NBuFOQXELEXA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Q6VmlLnMy0SSwop3akKW6b6MLrvGGlbgwLDzfQ81C81nfUnv5lXxDkYZ3NF2wbNfdPynzJ+/97P/fdiB+iFRCrx83AUK916iL6daNyr7OdAo6JqqC3bBtAGb5MHHdOCJxfv1uftjEnpfWIBlB8O3ppKurjonANaHgjoFRViRBbc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Lz9Rmnua; arc=none smtp.client-ip=209.85.215.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Lz9Rmnua" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-7afd1aeac83so4181734a12.0 for ; Tue, 20 Aug 2024 03:24:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1724149462; x=1724754262; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dix3ORoee+sfVX+vgLhY+ruQb6NILRgW8sq48cMvmzI=; b=Lz9RmnuagzlntkOoyXZilx1wYYhoJ556dt6EPw+xfAc6nYALgdjIBfi5EVVsjdeKCj LiTv0AQ2L/BskF0mzUaMoF+5S2fK2ojELjLYEr9gP/K3CCsf3bcFNQiWqw5JxpgWQpAg 6jJ94jxeYW+MOKxSClipDYRWyKII/pVmNsDwW3/31u82J0UUKo/syMqzhvV4TPwRsaF+ luW2t3BfOKMdVHWVfZ5Z0YispVDSTCJVHhx14hjQ0EX0beY7rI37ScNvT0XJwQdWMP6K CUXmNVotITJjp7vOzNm5GKNf1ZdXQ2OrSzqxxJEFQR2Gm3+WJEKpR7zNgUJUKlnEmqte sjHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724149462; x=1724754262; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dix3ORoee+sfVX+vgLhY+ruQb6NILRgW8sq48cMvmzI=; b=CkvxujZuwYzyoSiVKa6jqzdAgMEdCJstfrFlRxgQ+Y/kF22k8StOWOXcH1j60UQmBS QqPgsAM5kME/aKLfO8Ino1CSPtlydI2y1a+i8zrLoQ0yG5QtQGfJiyIQ/JJ2vYSHOh9J k+DxFQTHxvxLF0NVRZT5+Fks3HjJTtRhLuPSNSpZZDTdGKRLQaNzDwcriD4kSLKzA1a5 Sk7FHTJTyVDolmlPrFYL5p4T4RqhutEFBjmq3M8vZx5I3kEp/rBYk9WAi+/ZoR41S7pi rkwn77crAfrnFnScRHKiC/M8TslX/62kJExBSWXjWhuU2QKoYBq7RzivIG26+hJwwt0G W3OA== X-Gm-Message-State: AOJu0YwV59pDZvUDWXVSlWVhxFYflbIYMHZsbESntKeDVJVKs5iCwxC1 WQwdSa7rmHnrITrII5RKjHnbtaagGRdISlKQ89zisJHHCOekR/C76Nk/9wsK X-Google-Smtp-Source: AGHT+IFboRhfFfK6sJveLRpVelQkD6+XJdENs+Gn/oPH59+dGvFKuW1xBnfWwFhvBluRj+6b3g61lQ== X-Received: by 2002:a17:90b:38c7:b0:2c7:49b4:7e3a with SMTP id 98e67ed59e1d1-2d47321a170mr3591956a91.7.1724149461615; Tue, 20 Aug 2024 03:24:21 -0700 (PDT) Received: from honey-badger.. ([38.34.87.7]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d3e3174bfdsm8976166a91.27.2024.08.20.03.24.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Aug 2024 03:24:21 -0700 (PDT) From: Eduard Zingerman To: bpf@vger.kernel.org, ast@kernel.org Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, kernel-team@fb.com, yonghong.song@linux.dev, hffilwlqm@gmail.com, Eduard Zingerman Subject: [PATCH bpf-next v3 8/8] selftests/bpf: validate __xlated same way as __jited Date: Tue, 20 Aug 2024 03:23:57 -0700 Message-ID: <20240820102357.3372779-10-eddyz87@gmail.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240820102357.3372779-1-eddyz87@gmail.com> References: <20240820102357.3372779-1-eddyz87@gmail.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Both __xlated and __jited work with disassembly. It is logical to have both work in a similar manner. This commit updates __xlated macro handling in test_loader.c by making it expect matches on sequential lines, same way as __jited operates. For example: __xlated("1: *(u64 *)(r10 -16) = r1") ;; matched on line N __xlated("3: r0 = &(void __percpu *)(r0)") ;; matched on line N+1 Also: __xlated("1: *(u64 *)(r10 -16) = r1") ;; matched on line N __xlated("...") ;; not matched __xlated("3: r0 = &(void __percpu *)(r0)") ;; mantched on any ;; line >= N Signed-off-by: Eduard Zingerman --- .../selftests/bpf/progs/verifier_nocsr.c | 53 ++++++++++++++++++- tools/testing/selftests/bpf/test_loader.c | 8 ++- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/verifier_nocsr.c b/tools/testing/selftests/bpf/progs/verifier_nocsr.c index a7fe277e5167..666c736d196f 100644 --- a/tools/testing/selftests/bpf/progs/verifier_nocsr.c +++ b/tools/testing/selftests/bpf/progs/verifier_nocsr.c @@ -78,6 +78,7 @@ __naked void canary_arm64_riscv64(void) SEC("raw_tp") __arch_x86_64 __xlated("1: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("3: exit") __success __naked void canary_zero_spills(void) @@ -94,7 +95,9 @@ SEC("raw_tp") __arch_x86_64 __log_level(4) __msg("stack depth 16") __xlated("1: *(u64 *)(r10 -16) = r1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r2 = *(u64 *)(r10 -16)") __success __naked void wrong_reg_in_pattern1(void) @@ -113,7 +116,9 @@ __naked void wrong_reg_in_pattern1(void) SEC("raw_tp") __arch_x86_64 __xlated("1: *(u64 *)(r10 -16) = r6") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r6 = *(u64 *)(r10 -16)") __success __naked void wrong_reg_in_pattern2(void) @@ -132,7 +137,9 @@ __naked void wrong_reg_in_pattern2(void) SEC("raw_tp") __arch_x86_64 __xlated("1: *(u64 *)(r10 -16) = r0") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r0 = *(u64 *)(r10 -16)") __success __naked void wrong_reg_in_pattern3(void) @@ -151,7 +158,9 @@ __naked void wrong_reg_in_pattern3(void) SEC("raw_tp") __arch_x86_64 __xlated("2: *(u64 *)(r2 -16) = r1") +__xlated("...") __xlated("4: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("6: r1 = *(u64 *)(r10 -16)") __success __naked void wrong_base_in_pattern(void) @@ -171,7 +180,9 @@ __naked void wrong_base_in_pattern(void) SEC("raw_tp") __arch_x86_64 __xlated("1: *(u64 *)(r10 -16) = r1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r2 = 1") __success __naked void wrong_insn_in_pattern(void) @@ -191,7 +202,9 @@ __naked void wrong_insn_in_pattern(void) SEC("raw_tp") __arch_x86_64 __xlated("2: *(u64 *)(r10 -16) = r1") +__xlated("...") __xlated("4: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("6: r1 = *(u64 *)(r10 -8)") __success __naked void wrong_off_in_pattern1(void) @@ -211,7 +224,9 @@ __naked void wrong_off_in_pattern1(void) SEC("raw_tp") __arch_x86_64 __xlated("1: *(u32 *)(r10 -4) = r1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r1 = *(u32 *)(r10 -4)") __success __naked void wrong_off_in_pattern2(void) @@ -230,7 +245,9 @@ __naked void wrong_off_in_pattern2(void) SEC("raw_tp") __arch_x86_64 __xlated("1: *(u32 *)(r10 -16) = r1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r1 = *(u32 *)(r10 -16)") __success __naked void wrong_size_in_pattern(void) @@ -249,7 +266,9 @@ __naked void wrong_size_in_pattern(void) SEC("raw_tp") __arch_x86_64 __xlated("2: *(u32 *)(r10 -8) = r1") +__xlated("...") __xlated("4: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("6: r1 = *(u32 *)(r10 -8)") __success __naked void partial_pattern(void) @@ -275,11 +294,15 @@ __xlated("1: r2 = 2") /* not patched, spills for -8, -16 not removed */ __xlated("2: *(u64 *)(r10 -8) = r1") __xlated("3: *(u64 *)(r10 -16) = r2") +__xlated("...") __xlated("5: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("7: r2 = *(u64 *)(r10 -16)") __xlated("8: r1 = *(u64 *)(r10 -8)") /* patched, spills for -24, -32 removed */ +__xlated("...") __xlated("10: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("12: exit") __success __naked void min_stack_offset(void) @@ -308,7 +331,9 @@ __naked void min_stack_offset(void) SEC("raw_tp") __arch_x86_64 __xlated("1: *(u64 *)(r10 -8) = r1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r1 = *(u64 *)(r10 -8)") __success __naked void bad_fixed_read(void) @@ -330,7 +355,9 @@ __naked void bad_fixed_read(void) SEC("raw_tp") __arch_x86_64 __xlated("1: *(u64 *)(r10 -8) = r1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r1 = *(u64 *)(r10 -8)") __success __naked void bad_fixed_write(void) @@ -352,7 +379,9 @@ __naked void bad_fixed_write(void) SEC("raw_tp") __arch_x86_64 __xlated("6: *(u64 *)(r10 -16) = r1") +__xlated("...") __xlated("8: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("10: r1 = *(u64 *)(r10 -16)") __success __naked void bad_varying_read(void) @@ -379,7 +408,9 @@ __naked void bad_varying_read(void) SEC("raw_tp") __arch_x86_64 __xlated("6: *(u64 *)(r10 -16) = r1") +__xlated("...") __xlated("8: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("10: r1 = *(u64 *)(r10 -16)") __success __naked void bad_varying_write(void) @@ -406,7 +437,9 @@ __naked void bad_varying_write(void) SEC("raw_tp") __arch_x86_64 __xlated("1: *(u64 *)(r10 -8) = r1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r1 = *(u64 *)(r10 -8)") __success __naked void bad_write_in_subprog(void) @@ -438,7 +471,9 @@ __naked static void bad_write_in_subprog_aux(void) SEC("raw_tp") __arch_x86_64 __xlated("1: *(u64 *)(r10 -8) = r1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r1 = *(u64 *)(r10 -8)") __success __naked void bad_helper_write(void) @@ -466,13 +501,19 @@ SEC("raw_tp") __arch_x86_64 /* main, not patched */ __xlated("1: *(u64 *)(r10 -8) = r1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("5: r1 = *(u64 *)(r10 -8)") +__xlated("...") __xlated("9: call pc+1") +__xlated("...") __xlated("10: exit") /* subprogram, patched */ __xlated("11: r1 = 1") +__xlated("...") __xlated("13: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("15: exit") __success __naked void invalidate_one_subprog(void) @@ -510,12 +551,16 @@ SEC("raw_tp") __arch_x86_64 /* main */ __xlated("0: r1 = 1") +__xlated("...") __xlated("2: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("4: call pc+1") __xlated("5: exit") /* subprogram */ __xlated("6: r1 = 1") +__xlated("...") __xlated("8: r0 = &(void __percpu *)(r0)") +__xlated("...") __xlated("10: *(u64 *)(r10 -16) = r1") __xlated("11: exit") __success @@ -576,7 +621,9 @@ __log_level(4) __msg("stack depth 16") /* may_goto counter at -16 */ __xlated("0: *(u64 *)(r10 -16) =") __xlated("1: r1 = 1") +__xlated("...") __xlated("3: r0 = &(void __percpu *)(r0)") +__xlated("...") /* may_goto expansion starts */ __xlated("5: r11 = *(u64 *)(r10 -16)") __xlated("6: if r11 == 0x0 goto pc+3") @@ -623,13 +670,15 @@ __xlated("5: r0 = *(u32 *)(r0 +0)") __xlated("6: r2 =") __xlated("7: r3 = 0") __xlated("8: r4 = 0") +__xlated("...") /* ... part of the inlined bpf_loop */ __xlated("12: *(u64 *)(r10 -32) = r6") __xlated("13: *(u64 *)(r10 -24) = r7") __xlated("14: *(u64 *)(r10 -16) = r8") -/* ... */ +__xlated("...") __xlated("21: call pc+8") /* dummy_loop_callback */ /* ... last insns of the bpf_loop_interaction1 */ +__xlated("...") __xlated("28: r0 = 0") __xlated("29: exit") /* dummy_loop_callback */ @@ -670,7 +719,7 @@ __xlated("5: r0 = *(u32 *)(r0 +0)") __xlated("6: *(u64 *)(r10 -16) = r1") __xlated("7: call") __xlated("8: r1 = *(u64 *)(r10 -16)") -/* ... */ +__xlated("...") /* ... part of the inlined bpf_loop */ __xlated("15: *(u64 *)(r10 -40) = r6") __xlated("16: *(u64 *)(r10 -32) = r7") diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c index d588c612ac03..b229dd013355 100644 --- a/tools/testing/selftests/bpf/test_loader.c +++ b/tools/testing/selftests/bpf/test_loader.c @@ -365,6 +365,8 @@ static int parse_test_spec(struct test_loader *tester, const char *description = NULL; bool has_unpriv_result = false; bool has_unpriv_retval = false; + bool unpriv_xlated_on_next_line = true; + bool xlated_on_next_line = true; bool unpriv_jit_on_next_line; bool jit_on_next_line; bool collect_jit = false; @@ -461,12 +463,14 @@ static int parse_test_spec(struct test_loader *tester, spec->mode_mask |= UNPRIV; } } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX))) { - err = push_msg(msg, &spec->priv.expect_xlated); + err = push_disasm_msg(msg, &xlated_on_next_line, + &spec->priv.expect_xlated); if (err) goto cleanup; spec->mode_mask |= PRIV; } else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX_UNPRIV))) { - err = push_msg(msg, &spec->unpriv.expect_xlated); + err = push_disasm_msg(msg, &unpriv_xlated_on_next_line, + &spec->unpriv.expect_xlated); if (err) goto cleanup; spec->mode_mask |= UNPRIV;