Skip to content

global_asm! sym operands emit functions without function body #96623

Closed

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

Activity

  1. added
    A-inline-assemblyArea: Inline assembly (`asm!(…)`)
    requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.
    on May 2, 2022
  2. added 2 commits that reference this issue on May 5, 2022
    f838699
    149ab39
  3. added a commit that references this issue on May 6, 2022
    c7af4e6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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. When possible, use a F-* label instead.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions