Skip to content

Add support for suppressing name mangling with \01 prefix #1689

Description

@madsmtm

Normal Mach-O symbols are prefixed with _, non-prefixed symbols are reserved for special use. EDIT: Other platforms have similar name mangling rules.

LLVM allows you to opt out of symbol mangling by prefixing your symbol with the \01 byte marker, see the language reference. Cranelift should probably implement something similar.

For example, the linkme crate's distributed_slice uses this to access the special section$start$SEGMENT$SECTION and section$end$SEGMENT$SECTION symbols that the linker will replace with the address to respectively the start and end of the specified symbol.

The basic pattern they use is something like this:

use std::{mem, slice};

unsafe extern "Rust" {
    #[link_name = "\x01section$start$__DATA$__MY_SECTION"]
    static MY_SECTION_START: [fn(); 0];
    #[link_name = "\x01section$end$__DATA$__MY_SECTION"]
    static MY_SECTION_STOP: [fn(); 0];
}

#[used]
#[unsafe(link_section = "__DATA,__MY_SECTION,regular,no_dead_strip")]
static ITEM1: fn() = || println!("1");

#[used]
#[unsafe(link_section = "__DATA,__MY_SECTION,regular,no_dead_strip")]
static ITEM2: fn() = || println!("2");

fn main() {
    let start = (&raw const MY_SECTION_START).cast::<fn()>();
    let stop = (&raw const MY_SECTION_STOP).cast::<fn()>();

    let byte_offset = stop as usize - start as usize;
    let len = byte_offset / mem::size_of::<fn()>();
    let items = unsafe { slice::from_raw_parts(start, len) };

    for fnptr in items {
        fnptr();
    }
}

That is, add various items to a custom __DATA section, and then use the special directives to get the bounds of that section.

You can observe the difference with:

$ rustc foo.rs --emit obj -o llvm.o
$ objdump -t llvm.o | rg section
0000000000000000         *UND* section$end$__DATA$__MY_SECTION
0000000000000000         *UND* section$start$__DATA$__MY_SECTION

$ $cg_clif_dir/dist/rustc-clif foo.rs --emit obj -o clif.o
$ objdump -t clif.o | rg section
0000000000000000         *UND* _section$end$__DATA$__MY_SECTION
0000000000000000         *UND* _section$start$__DATA$__MY_SECTION

The Cranelift-compiled one will have symbol references with \x01_ (the 0x01 byte is invisible), while the LLVM-compiled one will have symbol references with no prefix.

EDIT: Related to #1520.

Metadata

Metadata

Assignees

No one assigned

    Labels

    O-macosOperating system: MacOS

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions