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

global_asm! sym operands emit functions without function body #96623

Closed
andylizi opened this issue May 2, 2022 · 0 comments · Fixed by #96650
Closed

global_asm! sym operands emit functions without function body #96623

andylizi opened this issue May 2, 2022 · 0 comments · Fixed by #96650
Labels
A-inline-assembly Area: inline asm!(..) C-bug Category: This is a bug. requires-nightly This issue requires a nightly compiler in some way.

Comments

@andylizi
Copy link
Contributor

andylizi commented May 2, 2022

Summary

If a function is only referenced by a sym operand in global_asm!, the definition/body of that function will not be emitted by the compiler, and the linker will fail with unresolved symbol error.

Reproduction

Save the following code as example.rs: (https://rust.godbolt.org/z/4jbf3eWjb)

#![no_std]
#![no_main]
#![feature(asm_sym)]
use core::arch::global_asm;

fn foo() {
    loop {}
}

static MY_STATIC: i32 = 0;

global_asm!(".global _start", "_start:", "call {}", sym foo);                       // ^1
// global_asm!(".global _start", "_start:", "lea rax, [rip + {}]", sym MY_STATIC);  // ^2

// #[no_mangle]                                                                     // ^3
// unsafe extern "sysv64" fn _start() {
//     core::arch::asm!("call {}", sym foo)
// }

#[panic_handler]
fn handle_panic(_panic: &core::panic::PanicInfo<'_>) -> ! {
    //foo();                                                                        // ^4
    loop {}
}

(.global _start is there to stop the linker from pruning unreachable code.)

Run rustc example.rs -Cpanic=abort -Clink-args="-nostdlib" produces a linker error "undefined reference to example::main":

error: linking with `cc` failed: exit status: 1
  |
  = note: "cc" "-m64" "example.example.2372ba8c-cgu.0.rcgu.o" "-Wl,--as-needed" "-L" "/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-2a6a2797f7a73818.rlib" "/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-0e3656b1fda5fd7b.rlib" "/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-16d69221f10b0282.rlib" "-Wl,-Bdynamic" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-L" "/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "example" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro,-znow" "-nodefaultlibs" "-nostdlib"
note: /usr/bin/ld: example.example.2372ba8c-cgu.0.rcgu.o: in function `_start':
          example.2372ba8c-cgu.0:(.text+0x1): undefined reference to `example::foo'

objdump -td example.example.2372ba8c-cgu.0.rcgu.o verifies that example::foo is indeed missing:

0000000000000000 g       .text  0000000000000000 _start
0000000000000000         *UND*  0000000000000000 _ZN7example3foo17h902e29a481949057E

The emitted llvm-ir looks something like this:

module asm ".global _start"
module asm "_start:"
module asm "call _ZN7example3foo17h902e29a481949057E"

@llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @_ZN7example3foo17h902e29a481949057E to i8*)], section "llvm.metadata"

; example::foo
; Function Attrs: nounwind nonlazybind
declare void @_ZN7example3foo17h902e29a481949057E() unnamed_addr #1

Some observations

  • The problem only appears if the function in question isn't used anywhere else. If we uncomment line ^4, the resulting IR will be correctly emitted:

    ; omit identical part
    
    ; example::foo
    ; Function Attrs: nounwind nonlazybind
    define internal void @_ZN7example3foo17h902e29a481949057E() unnamed_addr #0 {
    start:
      br label %bb1
    bb1:                                              ; preds = %bb1, %start
      br label %bb1
    }
  • Only functions can reproduce, static items work fine, as per line ^2.

  • Only global_asm! can reproduce, asm! works fine, as per line ^3 and co.

Meta

rustc 1.62.0-nightly (7c4b47696 2022-04-30)
binary: rustc
commit-hash: 7c4b47696907d64eff5621a64eb3c6e795a9ec77
commit-date: 2022-04-30
host: x86_64-unknown-linux-gnu
release: 1.62.0-nightly
LLVM version: 14.0.1

cc @Amanieu #94468
@rustbot label +A-inline-assembly +requires-nightly

@andylizi andylizi added the C-bug Category: This is a bug. label May 2, 2022
@rustbot rustbot added A-inline-assembly Area: inline asm!(..) requires-nightly This issue requires a nightly compiler in some way. labels May 2, 2022
compiler-errors added a commit to compiler-errors/rust that referenced this issue May 5, 2022
Collect function instance used in `global_asm!` sym operand

The constants used in SymFn operands have FnDef type,
so the type of the constant identifies the function.

Fixes rust-lang#96623.
compiler-errors added a commit to compiler-errors/rust that referenced this issue May 6, 2022
Collect function instance used in `global_asm!` sym operand

The constants used in SymFn operands have FnDef type,
so the type of the constant identifies the function.

Fixes rust-lang#96623.
@bors bors closed this as completed in c7af4e6 May 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inline-assembly Area: inline asm!(..) C-bug Category: This is a bug. requires-nightly This issue requires a nightly compiler in some way.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants