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

Place &str in specific linker sections #70239

Open
korken89 opened this issue Mar 21, 2020 · 2 comments
Open

Place &str in specific linker sections #70239

korken89 opened this issue Mar 21, 2020 · 2 comments
Labels
A-linkage Area: linking into static, shared libraries and binaries C-feature-request Category: A feature request, i.e: not implemented / a PR. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@korken89
Copy link

In the usecase I am working on I want to store the string from core::any::type_name in a specific linker section to create an instrumentation tool for Embedded Rust micro controllers.
If the string is placed in .rodata it does not affect the tool, but when having only a few kB of memory storing these strings in the actual micro controller is a huge price to pay.
Rather only the generated ELF file, which the host can read, should have this info (i.e. in an INFO marked section).

As it is today one can place variables in specific sections as:

#[link_section = ".my_section"]
static S: u32 = 2; 

However, this is not possible for &str, the following:

#[link_section = ".my_section"]
static S: &str = "test"; 

Will place the string itself in .rodata, while placing the pointer and length in the section .my_section.
The recommended solution is to place the string in an array using something similar to the following:

union Transmute<T: Copy, U: Copy> {
    from: T,
    to: U,
}

const TN: &'static str = "my string";

#[link_section = ".my_section"]
static S: [u8; TN.as_bytes().len()] = unsafe {
    *Transmute::<*const [u8; TN.as_bytes().len()], &[u8; TN.as_bytes().len()]> {
        from: TN.as_ptr() as *const [u8; TN.as_bytes().len()],
    }
    .to
};

However this does not work on strings given from (non-const-fn) functions such as core::any::type_name, and the function take no arguments so the string must be coming from a literal somewhere.
Is there a way to make the strings from core::any::type_name (or similar functions) be placed in a specific linker section?
As the string is being placed in .rodata something is controlling this placement, I simply wish to change this.

The method stated above works in nightly, as one can use the #![feature(const_type_name)] feature to get the string as a const-fn. However I am unable to reproduce this in any way using stable rust.
Example playground of the nightly version: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=d5f5c7fbe90194640bd1918cc068c2db

@jonas-schievink jonas-schievink added A-linkage Area: linking into static, shared libraries and binaries C-feature-request Category: A feature request, i.e: not implemented / a PR. T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Mar 21, 2020
@luojia65
Copy link
Contributor

luojia65 commented Mar 12, 2021

This feature is also used when we need to share text section between contexts. If the function called in custom section is still in original .text section, it would result in illegal page fault. Who should I refer to on this part of compiler feature?

@jamesmunns
Copy link
Member

At least as of recent compiler versions, I've come up with a sort of hacky way to achieve this (credit also to @cr1901 who solved the first half). TL;DR, you can define the str value as a const, and use that to produce a right-sized static which CAN be placed in a specific section.

I'm using it here with include bytes, but you could probably do something similar with strings?

Here, on the playground (same as below):

const EXAMPLE: &[u8] = include_bytes!("/proc/cpuinfo");
const EX_LEN: usize = EXAMPLE.len();
static BUF: [u8; EX_LEN] = {
    let mut arr = [0u8; EX_LEN];
    let mut idx = 0;
    while idx < EX_LEN {
        arr[idx] = EXAMPLE[idx];
        idx += 1;
    }
    arr
};

fn main() {
    println!("{}", BUF.len());
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries C-feature-request Category: A feature request, i.e: not implemented / a PR. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants