Skip to content

How to explain linker symbols used as integers (and not pointers to an allocation)? #554

Open
@ia0

Description

@ia0

Is there a way to explain linker symbols used only for their address? In particular when this address is not meant as a pointer but as an integer only. I have 2 examples.

Example 1: Using a linker symbol to communicate a number

The riscv-rt crate uses a _heap_size symbol to let users configure the heap size through the linker script. In particular, they have a code that looks like this in their documentation:

extern "C" {
    static _sheap: u8;
    static _heap_size: u8;
}

fn main() {
    unsafe {
        let heap_bottom = &_sheap as *const u8 as usize;
        let heap_size = &_heap_size as *const u8 as usize;
        some_allocator::initialize(heap_bottom, heap_size);
    }
}

We could argue whether u8 is the correct type. Let's assume it's a ZST to simplify this particular case.

Example 2: Using a linker symbol to "allocate" a unique (to the program) value

The defmt crate uses static variables in specific linker section (with specific name, but this is orthogonal to this issue) to allocate identifiers for interned strings. The address of the static variable (aka the value of the symbol) is the identifier. The static variable does not represent a proper allocation, and actually won't have any allocation at all from Rust point of view (the linker section is NOLOAD).

The proc-macro generating those static variables looks like this:

    quote!(
        #[cfg_attr(target_os = "macos", link_section = #section_for_macos)]
        #[cfg_attr(not(target_os = "macos"), link_section = #section)]
        #[export_name = #sym_name]
        static #name: u8 = 0;
    )

In this case, the u8 type matters. That's how the identifiers are unique and consecutive (they start at 1 so they can fit in a u16).

Related issues

I'm creating a new issue, although there are many related issues, because I feel this particular concern of static variables without allocation is not addressed yet. Here are the related issues:

Please dedup if I missed an issue or I'm wrong in my analysis.

Theoretical suggestion

There could be an attribute to indicate when a static does not have an allocation. It is thus UB for a static to not have an allocation if it does not have this attribute. Such "inaccessible statics" can only have their address taken. They don't have an allocation and can't be dereferenced.

#[inaccessible_static]
static MY_ADDRESS_IS_AN_IDENTIFIER: u8 = 0;

unsafe extern "C" {
    #[inaccessible_static]
    static MY_ADDRESS_IS_A_VALUE: ();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions