Skip to content

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

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

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

Conversation

@madsmtm

@madsmtm madsmtm commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

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)] = &[

@madsmtm madsmtm Apr 19, 2026

Copy link
Copy Markdown
Contributor Author

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Using tables here is fine by me.

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
@rustbot

rustbot commented May 24, 2026

Copy link
Copy Markdown
Collaborator

☔ The latest upstream changes (possibly 9446d0d) made this pull request unmergeable. Please resolve the merge conflicts.

Comment thread src/constant.rs
// <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)] = &[
("regular", object::macho::S_REGULAR),

@bjorn3 bjorn3 May 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe use object::macho? Or even put those two tables in an inline submodule with use object::macho::*?

View changes since the review

@bjorn3

bjorn3 commented May 24, 2026

Copy link
Copy Markdown
Member

I updated Cranelift earlier today, so it should work after a rebase.

@bjorn3

bjorn3 commented Jun 24, 2026

Copy link
Copy Markdown
Member

@madsmtm did you intend to work on this further or do you want me to pick it up?

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)

3 participants