From patchwork Fri Aug 21 19:00:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vineet Gupta X-Patchwork-Id: 141964 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9B37B4BAE7D6 for ; Fri, 21 Aug 2026 19:00:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9B37B4BAE7D6 Authentication-Results: sourceware.org; dkim=fail reason="signature verification failed" (1024-bit key, unprotected) header.d=linux.dev header.i=@linux.dev header.a=rsa-sha256 header.s=key1 header.b=nq9SjM1G X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mta1.migadu.com (out-25.mta1.migadu.com [IPv6:2001:41d0:203:375::19]) by sourceware.org (Postfix) with ESMTPS id DDF1D4BA79A7 for ; Fri, 21 Aug 2026 19:00:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DDF1D4BA79A7 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linux.dev ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DDF1D4BA79A7 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2001:41d0:203:375::19 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1787338825; cv=none; b=GvwMmtIRdMHL0oDSIREGnpAbwihju8qJk4jGmeGdWOT5cyqbWxF52wcjZF2SJt+0GpdjLdA4+vFYE60ICj5duf07ftBwebayEcS9V7FLeTBrGaLq7w+mi67X15ZazretcY/e0nU8g4ZiFVxHRaDFAGTUmp6Lgrf8YTpLMDxHpvs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1787338825; c=relaxed/simple; bh=rZXs07UEGeAFSAoe5jl03ZshkM0kJj0frMIeAu3CADQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=VEGMb5L1Ez/i26bdWCaIYRqJnEG2RX2fnIBpFZpjkgtazIJVXd+9mElVaKhXvIKBKiq3K1s8dC7Ay+/wjUW3Gcw0FSzprD3HgB7Q/6nZjd4PWyJQ0wM1V5pTtHAoqB4sPfFFcGX2prgl/Y/5jnT0Uet+RWGjeOEDk7ttZ2Za0pk= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=linux.dev header.i=@linux.dev header.a=rsa-sha256 header.s=key1 header.b=nq9SjM1G DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DDF1D4BA79A7 X-Envelope-To: binutils@sourceware.org DKIM-Signature: a=rsa-sha256; bh=rZXs07UEGeAFSAoe5jl03ZshkM0kJj0frMIeAu3CADQ=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787338822; v=1; x=1787943622; b=nq9SjM1GmzWCMHjS5n+CFPJgDMzV4kYr0GpFi+5hT5BWwwRtoPN+Ibv4XHfo5Cvxnf2kcAKI 2zVGX3aY7knJBat0Tdk2bs+IuruJGjZGwYWrkAT6MrmxEyI/oEORunvnMyihWp/OBaGk2vuTFNP LCBcw+P62+jSz/vMr9Lt0yWg= X-Envelope-To: binutils@sourceware.org Received: from gvineet-fedora-PF5JGVFY (67.169.75.212) by smtp.migadu.com with ESMTPS id f3d318d1e2e8a7fc; Fri, 21 Aug 2026 19:00:22 +0000 X-Mizu-Trace-ID: f3d318d1e2e8a7fc X-Migadu-Flow: FLOW_OUT From: Vineet Gupta To: binutils@sourceware.org Cc: bpf@gcc.gnu.org, jose.marchesi@oracle.com, ast@kernel.org, Vineet Gupta Subject: [PATCH] PR 34558: bpf: don't mis-assemble `gotol' with signed offset Date: Fri, 21 Aug 2026 12:00:14 -0700 Message-ID: <20260821190014.993359-1-vineet.gupta@linux.dev> X-Mailer: git-send-email 2.55.0 MIME-Version: 1.0 X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_PBL, SPF_HELO_PASS, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org `gotol +1' is assembled as if it were `goto l +1' `gotol +imm' is the canonical form in the BPF instruction set documentation, and it is what LLVM emits and accepts, so it needs to work. The reason is the asm templates for the two unconditional jumps: BPF_INSN_JAR "goto%w%d16" BPF_INSN_JAL "gotol%w%d32" where %w matches zero or more whitespace characters. JAR sorts before JAL in the opcode table so it tries to match first and succeeds as `goto' and `l +1', with `l' being an undefined symbol. This ends up as JA (opcode 0x05, with the displacement in the 16-bit `off' field) plus an R_BPF_GNU_64_16 relocation against an undefined symbol `l', rather than as JAL (opcode 0x06, displacement in the 32-bit `imm' field). No diagnostic is emitted. The signed form -1 is similarly affected. For non-signed forms, `gotol 1' or `gotol 1f', the remainder does not parse as a single expression, the JAR template fails, and JAL is reached and matched correctly. The normal dialect is not affected either, as `ja%W%d16' requires at least one whitespace character after the mnemonic. The fix is to reject a template whose literal text stops in the middle of a name: if the character last matched from the template is part of a name and the input continues with another name character, then the template has only matched a prefix of a longer mnemonic and does not apply. Other templates are then given a chance to match the whole mnemonic. This also covers the compound conditional jumps, whose templates embed `goto%w%d16'. Existing coverage exercised `gotol' only with a label operand, which is why this went unnoticed. PR gas/34558 gas/ * config/tc-bpf.c (md_assemble): Do not let a template match when its literal text ends mid-name and the input continues with a name character. * testsuite/gas/bpf/jump-gotol-signed-pseudoc.s: New test. * testsuite/gas/bpf/jump-gotol-signed-pseudoc.d: New test. * testsuite/gas/bpf/bpf.exp: Run it. --- gas/config/tc-bpf.c | 23 ++++++++++++++++++- gas/testsuite/gas/bpf/bpf.exp | 1 + .../gas/bpf/jump-gotol-signed-pseudoc.d | 15 ++++++++++++ .../gas/bpf/jump-gotol-signed-pseudoc.s | 10 ++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.d create mode 100644 gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.s diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c index 8d48b128fb90..9b207c2e2389 100644 --- a/gas/config/tc-bpf.c +++ b/gas/config/tc-bpf.c @@ -1506,7 +1506,28 @@ md_assemble (char *str ATTRIBUTE_UNUSED) } else if (*(p + 1) == 'w') { - /* Expect zero or more spaces. */ + /* Expect zero or more spaces. + + If the template text matched so far ends in a name + character and the input continues with another name + character, then the template only matched a prefix of a + longer mnemonic written in the input, and this template + does not apply. Rejecting it here lets a subsequent + template have a go at the whole mnemonic. + + Without this, `gotol +1' matches the `goto%w%d16' + template, with `l +1' parsed as the branch offset + expression, silently assembling to JA (opcode 0x05) plus + a relocation against an undefined symbol `l' instead of + to JAL (opcode 0x06). */ + if (!is_whitespace (*s) + && p > template + && is_part_of_name (*(p - 1)) + && is_part_of_name (*s)) + { + PARSE_ERROR ("expected white space, got '%s'", s); + break; + } while (is_whitespace (*s)) s += 1; p += 2; diff --git a/gas/testsuite/gas/bpf/bpf.exp b/gas/testsuite/gas/bpf/bpf.exp index f19322122527..efd1eab08f72 100644 --- a/gas/testsuite/gas/bpf/bpf.exp +++ b/gas/testsuite/gas/bpf/bpf.exp @@ -38,6 +38,7 @@ if {[istarget bpf*-*-*]} { run_dump_test jump-pseudoc run_dump_test jump32 run_dump_test jump32-pseudoc + run_dump_test jump-gotol-signed-pseudoc run_dump_test atomic-v1 run_dump_test atomic run_dump_test atomic-pseudoc diff --git a/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.d b/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.d new file mode 100644 index 000000000000..ee4146acd996 --- /dev/null +++ b/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.d @@ -0,0 +1,15 @@ +#as: -EL -mdialect=pseudoc +#objdump: -dr -M dec,pseudoc +#source: jump-gotol-signed-pseudoc.s +#name: eBPF gotol with signed offsets, pseudoc syntax + +.*: +file format .*bpf.* + +Disassembly of section .text: + +0+ <.text>: + 0: 06 00 00 00 01 00 00 00 gotol 1 + 8: 06 00 00 00 ff ff ff ff gotol -1 + 10: 06 00 00 00 01 00 00 00 gotol 1 + 18: 06 00 00 00 00 00 00 00 gotol 0 + 20: 06 00 00 00 00 00 00 00 gotol 0 diff --git a/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.s b/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.s new file mode 100644 index 000000000000..295afd6313d5 --- /dev/null +++ b/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.s @@ -0,0 +1,10 @@ + # Signed branch offsets for the pseudo-C `gotol'. PR gas/34558: + # these used to match the shorter `goto' template, with the + # trailing `l' parsed as the start of the offset expression. + .text + gotol +1 + gotol -1 + gotol 1 + gotol 1f +1: + gotol 0