Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error: cannot jump from this asm goto statement to one of its possible targets #1886

Closed
nathanchance opened this issue Jul 10, 2023 · 6 comments
Assignees
Labels
asm goto related to the implementation of asm goto [BUG] llvm A bug that should be fixed in upstream LLVM [FIXED][LLVM] 17 This bug was fixed in LLVM 17.0

Comments

@nathanchance
Copy link
Member

With perf: Simplify find_get_pmu_context() (hash may have changed, check for the most recent core/guards branch):

$ make -skj"$(nproc)" ARCH=powerpc CC=clang CROSS_COMPILE=powerpc-linux-gnu- LLVM_IAS=0 mrproper 44x/akebono_defconfig kernel/events/core.o
kernel/events/core.c:4807:4: error: cannot jump from this asm goto statement to one of its possible targets
 4807 |                         WARN_ON_ONCE(epc->ctx != ctx);
      |                         ^
include/asm-generic/bug.h:113:3: note: expanded from macro 'WARN_ON_ONCE'
  113 |                 __WARN_FLAGS(BUGFLAG_ONCE |                     \
      |                 ^
arch/powerpc/include/asm/bug.h:101:2: note: expanded from macro '__WARN_FLAGS'
  101 |         WARN_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags), __label_warn_on); \
      |         ^
arch/powerpc/include/asm/bug.h:77:2: note: expanded from macro 'WARN_ENTRY'
   77 |         asm_volatile_goto(                              \
      |         ^
include/linux/compiler_types.h:328:33: note: expanded from macro 'asm_volatile_goto'
  328 | #define asm_volatile_goto(x...) asm goto(x)
      |                                 ^
kernel/events/core.c:4776:4: note: possible target of asm goto statement
 4776 |                         WARN_ON_ONCE(epc->ctx != ctx);
      |                         ^
include/asm-generic/bug.h:113:3: note: expanded from macro 'WARN_ON_ONCE'
  113 |                 __WARN_FLAGS(BUGFLAG_ONCE |                     \
      |                 ^
arch/powerpc/include/asm/bug.h:104:9: note: expanded from macro '__WARN_FLAGS'
  104 |                                                                 \
      |                                                                 ^
kernel/events/core.c:4783:8: note: jump exits scope of variable with __attribute__((cleanup))
 4783 |         void *new __free(kfree) = kzalloc(sizeof(*epc), GFP_KERNEL);
      |               ^
kernel/events/core.c:4776:4: error: cannot jump from this asm goto statement to one of its possible targets
 4776 |                         WARN_ON_ONCE(epc->ctx != ctx);
      |                         ^
include/asm-generic/bug.h:113:3: note: expanded from macro 'WARN_ON_ONCE'
  113 |                 __WARN_FLAGS(BUGFLAG_ONCE |                     \
      |                 ^
arch/powerpc/include/asm/bug.h:101:2: note: expanded from macro '__WARN_FLAGS'
  101 |         WARN_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags), __label_warn_on); \
      |         ^
arch/powerpc/include/asm/bug.h:77:2: note: expanded from macro 'WARN_ENTRY'
   77 |         asm_volatile_goto(                              \
      |         ^
include/linux/compiler_types.h:328:33: note: expanded from macro 'asm_volatile_goto'
  328 | #define asm_volatile_goto(x...) asm goto(x)
      |                                 ^
kernel/events/core.c:4807:4: note: possible target of asm goto statement
 4807 |                         WARN_ON_ONCE(epc->ctx != ctx);
      |                         ^
include/asm-generic/bug.h:113:3: note: expanded from macro 'WARN_ON_ONCE'
  113 |                 __WARN_FLAGS(BUGFLAG_ONCE |                     \
      |                 ^
arch/powerpc/include/asm/bug.h:104:9: note: expanded from macro '__WARN_FLAGS'
  104 |                                                                 \
      |                                                                 ^
kernel/events/core.c:4783:8: note: jump bypasses initialization of variable with __attribute__((cleanup))
 4783 |         void *new __free(kfree) = kzalloc(sizeof(*epc), GFP_KERNEL);
      |               ^
2 errors generated.

Looking at the preprocessed source, I wonder if something is going sideways with __label_warn_on in __WARN_FLAGS()?

For what it is worth, this code may be killed for an independent reason: https://lore.kernel.org/bb8b901b51f1beaaf9fa86ce8ce9b8191817b3e1.1687539638.git.christophe.leroy@csgroup.eu/

@nathanchance
Copy link
Member Author

For what it is worth, this code may be killed for an independent reason: https://lore.kernel.org/bb8b901b51f1beaaf9fa86ce8ce9b8191817b3e1.1687539638.git.christophe.leroy@csgroup.eu/

Seems like this is eminent: https://lore.kernel.org/20230712134552.534955-1-mpe@ellerman.id.au/

I still think this is worth looking into because there is nothing preventing this from reoccurring with another architecture at some point.

Based on #1887, it seems like something is going wrong with the scope of local labels in statement expressions?

@nathanchance
Copy link
Member Author

Corentin's comment at https://reviews.llvm.org/D154696#4494899 would likely explain this issue too, as we are dealing with local labels here too.

@nickdesaulniers
Copy link
Member

nickdesaulniers commented Jul 14, 2023

reduced test case:

void bar(void **);
void* baz();

int  foo (void) {
    {
        asm goto("jmp %l0"::::l0);
        return 0;
l0:
        return 1;
    }
    void *x __attribute__((cleanup(bar))) = baz();
    {
        asm goto("jmp %l0"::::l1);
        return 42;
l1:
        return 0xff;
    }
}

whether or not the labels are local is a red herring; if we have unique labels in a fn, we get the same error. Same for GNU C statement expressions.

@nickdesaulniers nickdesaulniers added [BUG] llvm A bug that should be fixed in upstream LLVM and removed [BUG] Untriaged Something isn't working labels Jul 14, 2023
@nickdesaulniers
Copy link
Member

Looks like when support for asm goto was first introduced into clang, b8fee677bf8e2, a bug was introduced in JumpScopeChecker::VerifyIndirectOrAsmJumps where each GCCAsmStmt is cross validated against each LabelDecl, regardless of whether that LabelDecl is even a target of that GCCAsmStmt or not. JumpScopeChecker::VerifyIndirectOrAsmJumps should only check the reachability of LabelDecl's of actual targets of GCCAsmStmt's.

My example above demonstrates more clearly than the original reproducer (where the labels had the same name, since they were local):

x.c:15:9: error: cannot jump from this asm goto statement to one of its possible targets
   15 |         asm goto("jmp %l0"::::l1);
      |         ^
x.c:9:1: note: possible target of asm goto statement
    9 | l0:
      | ^
...
x.c:7:9: error: cannot jump from this asm goto statement to one of its possible targets
    7 |         asm goto("jmp %l0"::::l0);
      |         ^
x.c:17:1: note: possible target of asm goto statement
   17 | l1:
      | ^
...

which is [more] obviously incorrect.

@nickdesaulniers
Copy link
Member

@nickdesaulniers nickdesaulniers added [PATCH] Submitted A patch has been submitted for review and removed [ARCH] powerpc This bug impacts ARCH=powerpc labels Jul 14, 2023
@nickdesaulniers nickdesaulniers added [FIXED][LLVM] 17 This bug was fixed in LLVM 17.0 and removed [PATCH] Submitted A patch has been submitted for review labels Jul 21, 2023
@nickdesaulniers
Copy link
Member

Note to self since this might pop up again for future kernel patches with clang-16 or older:

asm goto and goto need to check scopes to see if initializers or __attribute__((cleanup())) callbacks might be skipped. clang-9 through clang-16 had a bug specifically for asm goto where all asm gotos in a function were cross checked across all labels in the function, regardless of whether that was actually a target of the asm goto or not. This was fixed in clang-17 to only validate the actual targets of each asm goto.

Code that needs to be compiler version portable might need to rework code if it contains asm goto and labels that cross the boundaries of initializers or __attribute__((cleanup())) callbacks.

veselypeta pushed a commit to veselypeta/cherillvm that referenced this issue Sep 7, 2024
The current behavior of JumpScopeChecker::VerifyIndirectOrAsmJumps was
to cross validate the scope of every jumping statement (goto, asm goto)
against the scope of every label (even if the label was not even a
possible target of the asm goto).

When we have multiple asm goto's with unique targets, we could trigger
false positive build errors complaining that labels that weren't even in
the asm goto's label list could not be jumped to.  Example:

    error: cannot jump from this asm goto statement to one of its possible targets
    asm goto(""::::foo);
    note: possible target of asm goto statement
    bar:
    ^

Fixes: ClangBuiltLinux/linux#1886

Reviewed By: void, jyu2, rjmccall

Differential Revision: https://reviews.llvm.org/D155342
arichardson pushed a commit to CTSRD-CHERI/llvm-project that referenced this issue Jan 28, 2025
The current behavior of JumpScopeChecker::VerifyIndirectOrAsmJumps was
to cross validate the scope of every jumping statement (goto, asm goto)
against the scope of every label (even if the label was not even a
possible target of the asm goto).

When we have multiple asm goto's with unique targets, we could trigger
false positive build errors complaining that labels that weren't even in
the asm goto's label list could not be jumped to.  Example:

    error: cannot jump from this asm goto statement to one of its possible targets
    asm goto(""::::foo);
    note: possible target of asm goto statement
    bar:
    ^

Fixes: ClangBuiltLinux/linux#1886

Reviewed By: void, jyu2, rjmccall

Differential Revision: https://reviews.llvm.org/D155342
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
asm goto related to the implementation of asm goto [BUG] llvm A bug that should be fixed in upstream LLVM [FIXED][LLVM] 17 This bug was fixed in LLVM 17.0
Projects
None yet
Development

No branches or pull requests

2 participants