Skip to content

Parse and set Mach-O section type and attributes#1648

Draft
madsmtm wants to merge 1 commit intomainfrom
madsmtm/mach-o-section-flags
Draft

Parse and set Mach-O section type and attributes#1648
madsmtm wants to merge 1 commit intomainfrom
madsmtm/mach-o-section-flags

Conversation

@madsmtm
Copy link
Copy Markdown
Contributor

@madsmtm madsmtm commented Apr 19, 2026

Mach-O sections have a 32-bit "flags" parameter, which contains 8 bits for a "section type", and 24 bits for "attributes". These can be controlled with #[link_section = ...] like so:

// Sets the section type to S_MOD_INIT_FUNC_POINTERS
#[unsafe(link_section = "__DATA,__mod_init_func,mod_init_funcs")]
static CONSTRUCTOR: extern "C" fn() = ...;

// Sets the section type to S_CSTRING_LITERALS
#[link_section = "__TEXT,__cstring,cstring_literals"]
static NAME_DATA: [u8; 4] = b"foo\0";

#[unsafe(link_section = "__TEXT,__text,regular,pure_instructions+no_dead_strip")]
static LINKER_USED_INSTRUCTIONS: [u8; 10] = ...;

The default section type is "regular" (S_REGULAR).

This PR parses the section type names and attribute names understood by LLVM, and convert them to the corresponding Mach-O flags.

Fixes #1588.
Depends on bytecodealliance/wasmtime#13137.

Related to rust-lang/rust#155065, we could also put this parsing logic higher up, to rely less on LLVM / get diagnostics with spans for this on all backends?

Comment thread src/constant.rs
// We support the same custom section type / attrs naming as LLVM:
// <https://github.com/llvm/llvm-project/blob/llvmorg-22.1.3/llvm/lib/MC/MCSectionMachO.cpp#L23-L91>
// <https://github.com/llvm/llvm-project/blob/llvmorg-22.1.3/llvm/include/llvm/BinaryFormat/MachO.h#L120-L223>
const MACHO_SECTION_TYPES: &[(&str, u32)] = &[
Copy link
Copy Markdown
Contributor Author

@madsmtm madsmtm Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this as a table originally because I kinda wanted to print the available options / have suggestions for mistyped section types, but I ended up not implementing that, because I didn't really know if there were a good way to do so with rustc's diagnostic APIs?

I can do a match instead if you prefer?

View changes since the review

JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Apr 20, 2026
…trs, r=bjorn3

Add a test for Mach-O `#[link_section]` API inherited from LLVM

The format of the `#[link_section]` attribute is under-documented, but on Mach-O, I think it's roughly the following BNF:
```
LinkSection -> Segment `,` Section (`,` (SectionType (`,` (SectionAttributes)?)?)?)?
Segment -> <0 to 16 bytes>
Section -> <0 to 16 bytes>
SectionType -> `regular` | `zerofill` | `cstring_literals` | `4byte_literals` | `8byte_literals` | `literal_pointers` | `non_lazy_symbol_pointers` | `lazy_symbol_pointers` | `symbol_stubs` | `mod_init_funcs` | `mod_term_funcs` | `coalesced` | `interposing` | `16byte_literals` | `thread_local_regular` | `thread_local_zerofill` | `thread_local_variables` | `thread_local_variable_pointers` | `thread_local_init_function_pointers`
SectionAttributes -> SectionAttribute (`+` SectionAttribute)*
SectionAttribute -> `pure_instructions` | `no_toc` | `strip_static_syms` | `no_dead_strip` | `live_support`, `self_modifying_code` | `debug`
```

This PR adds a small test for a little part of this.

Once rust-lang#154429 is resolved, this should make it possible to test rust-lang/rustc_codegen_cranelift#1648 end-to-end.

r? bjorn3
rust-timer added a commit to rust-lang/rust that referenced this pull request Apr 20, 2026
Rollup merge of #155517 - madsmtm:test-macho-link-section-attrs, r=bjorn3

Add a test for Mach-O `#[link_section]` API inherited from LLVM

The format of the `#[link_section]` attribute is under-documented, but on Mach-O, I think it's roughly the following BNF:
```
LinkSection -> Segment `,` Section (`,` (SectionType (`,` (SectionAttributes)?)?)?)?
Segment -> <0 to 16 bytes>
Section -> <0 to 16 bytes>
SectionType -> `regular` | `zerofill` | `cstring_literals` | `4byte_literals` | `8byte_literals` | `literal_pointers` | `non_lazy_symbol_pointers` | `lazy_symbol_pointers` | `symbol_stubs` | `mod_init_funcs` | `mod_term_funcs` | `coalesced` | `interposing` | `16byte_literals` | `thread_local_regular` | `thread_local_zerofill` | `thread_local_variables` | `thread_local_variable_pointers` | `thread_local_init_function_pointers`
SectionAttributes -> SectionAttribute (`+` SectionAttribute)*
SectionAttribute -> `pure_instructions` | `no_toc` | `strip_static_syms` | `no_dead_strip` | `live_support`, `self_modifying_code` | `debug`
```

This PR adds a small test for a little part of this.

Once #154429 is resolved, this should make it possible to test rust-lang/rustc_codegen_cranelift#1648 end-to-end.

r? bjorn3
github-actions Bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Apr 21, 2026
…orn3

Add a test for Mach-O `#[link_section]` API inherited from LLVM

The format of the `#[link_section]` attribute is under-documented, but on Mach-O, I think it's roughly the following BNF:
```
LinkSection -> Segment `,` Section (`,` (SectionType (`,` (SectionAttributes)?)?)?)?
Segment -> <0 to 16 bytes>
Section -> <0 to 16 bytes>
SectionType -> `regular` | `zerofill` | `cstring_literals` | `4byte_literals` | `8byte_literals` | `literal_pointers` | `non_lazy_symbol_pointers` | `lazy_symbol_pointers` | `symbol_stubs` | `mod_init_funcs` | `mod_term_funcs` | `coalesced` | `interposing` | `16byte_literals` | `thread_local_regular` | `thread_local_zerofill` | `thread_local_variables` | `thread_local_variable_pointers` | `thread_local_init_function_pointers`
SectionAttributes -> SectionAttribute (`+` SectionAttribute)*
SectionAttribute -> `pure_instructions` | `no_toc` | `strip_static_syms` | `no_dead_strip` | `live_support`, `self_modifying_code` | `debug`
```

This PR adds a small test for a little part of this.

Once rust-lang/rust#154429 is resolved, this should make it possible to test rust-lang/rustc_codegen_cranelift#1648 end-to-end.

r? bjorn3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

O-macos Operating system: MacOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add support for mod_init_funcs (was compat: rust-ctor fails to trigger with Cranelift on MacOS, but works with LLVM)

1 participant