Skip to content

global_asm! sym operands emit functions without function body #96623

Closed
@andylizi

Description

@andylizi

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inline-assemblyArea: Inline assembly (`asm!(…)`)C-bugCategory: This is a bug.requires-nightlyThis issue requires a nightly compiler in some way.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions