Skip to content

Conversation

@cezarbbb
Copy link
Contributor

@cezarbbb cezarbbb commented Jan 12, 2026

In order to be able to export symbols from a specified upstream C static library, I redesigned a solution that, compared to a previous PR #150335 I submitted, will not have any extra symbols leaking out.

The following points should be noted:

  • This attribute will select and import the Global symbols of the first matching library it finds.
  • Developers should ensure that there are no libraries with the same name.
  • This modifier is only compatible with static linking kind
  • By default, upstream C static libraries will not export their Global symbols regardless of whether LTO optimization is enabled. However, after enabling this attribute, if the upstream C static library has LTO optimization enabled, the compiler will issue an error to inform the developer that the linked C library is invalid.

The test code is the same as the PR #150335.
Here are the results:

  1. cargo +include-libs rustc --release -- -L. -lstatic:+export-symbols=c_add
    (or you can use #[link(name = "c_add", kind= "static", modifier = "+export-symbols")] in the file)
                 U abort@GLIBC_2.2.5
                 U bcmp@GLIBC_2.2.5
0000000000014f60 T c_add
                 U calloc@GLIBC_2.2.5
                 U close@GLIBC_2.2.5
0000000000014f70 T c_sub
                 w __cxa_finalize@GLIBC_2.2.5
                 w __cxa_thread_atexit_impl@GLIBC_2.18
                 U dl_iterate_phdr@GLIBC_2.2.5
0000000000014ee0 T downstream_add
                 U __errno_location@GLIBC_2.2.5
                 U free@GLIBC_2.2.5
                 U fstat64@GLIBC_2.33
                 U getcwd@GLIBC_2.2.5
                 U getenv@GLIBC_2.2.5
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U lseek64@GLIBC_2.2.5
                 U malloc@GLIBC_2.2.5
                 U memcpy@GLIBC_2.14
                 U memmove@GLIBC_2.2.5
                 U memset@GLIBC_2.2.5
                 U mmap64@GLIBC_2.2.5
                 U munmap@GLIBC_2.2.5
                 U open64@GLIBC_2.2.5
                 U posix_memalign@GLIBC_2.2.5
                 U pthread_key_create@GLIBC_2.34
                 U pthread_key_delete@GLIBC_2.34
                 U pthread_setspecific@GLIBC_2.34
                 U read@GLIBC_2.2.5
                 U readlink@GLIBC_2.2.5
                 U realloc@GLIBC_2.2.5
                 U realpath@GLIBC_2.3
                 U stat64@GLIBC_2.33
                 w statx@GLIBC_2.28
                 U strlen@GLIBC_2.2.5
                 U syscall@GLIBC_2.2.5
                 U __tls_get_addr@GLIBC_2.3
                 U _Unwind_Backtrace@GCC_3.3
                 U _Unwind_DeleteException@GCC_3.0
                 U _Unwind_GetDataRelBase@GCC_3.0
                 U _Unwind_GetIP@GCC_3.0
                 U _Unwind_GetIPInfo@GCC_4.2.0
                 U _Unwind_GetLanguageSpecificData@GCC_3.0
                 U _Unwind_GetRegionStart@GCC_3.0
                 U _Unwind_GetTextRelBase@GCC_3.0
                 U _Unwind_RaiseException@GCC_3.0
                 U _Unwind_Resume@GCC_3.0
                 U _Unwind_SetGR@GCC_3.0
                 U _Unwind_SetIP@GCC_3.0
                 U write@GLIBC_2.2.5
                 U writev@GLIBC_2.2.5
  1. cargo +nightly rustc --release -- -L ./
                 U abort@GLIBC_2.2.5
                 U bcmp@GLIBC_2.2.5
                 U calloc@GLIBC_2.2.5
                 U close@GLIBC_2.2.5
                 w __cxa_finalize@GLIBC_2.2.5
                 w __cxa_thread_atexit_impl@GLIBC_2.18
                 U dl_iterate_phdr@GLIBC_2.2.5
0000000000011e10 T downstream_add
                 U __errno_location@GLIBC_2.2.5
                 U free@GLIBC_2.2.5
                 U fstat64@GLIBC_2.33
                 U getcwd@GLIBC_2.2.5
                 U getenv@GLIBC_2.2.5
                 w gettid@GLIBC_2.30
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U lseek64@GLIBC_2.2.5
                 U malloc@GLIBC_2.2.5
                 U memcpy@GLIBC_2.14
                 U memmove@GLIBC_2.2.5
                 U memset@GLIBC_2.2.5
                 U mmap64@GLIBC_2.2.5
                 U munmap@GLIBC_2.2.5
                 U open64@GLIBC_2.2.5
                 U posix_memalign@GLIBC_2.2.5
                 U pthread_key_create@GLIBC_2.34
                 U pthread_key_delete@GLIBC_2.34
                 U pthread_setspecific@GLIBC_2.34
                 U read@GLIBC_2.2.5
                 U readlink@GLIBC_2.2.5
                 U realloc@GLIBC_2.2.5
                 U realpath@GLIBC_2.3
                 U stat64@GLIBC_2.33
                 w statx@GLIBC_2.28
                 U strlen@GLIBC_2.2.5
                 U syscall@GLIBC_2.2.5
                 U __tls_get_addr@GLIBC_2.3
                 U _Unwind_Backtrace@GCC_3.3
                 U _Unwind_GetDataRelBase@GCC_3.0
                 U _Unwind_GetIP@GCC_3.0
                 U _Unwind_GetIPInfo@GCC_4.2.0
                 U _Unwind_GetLanguageSpecificData@GCC_3.0
                 U _Unwind_GetRegionStart@GCC_3.0
                 U _Unwind_GetTextRelBase@GCC_3.0
                 U _Unwind_RaiseException@GCC_3.0
                 U _Unwind_Resume@GCC_3.0
                 U _Unwind_SetGR@GCC_3.0
                 U _Unwind_SetIP@GCC_3.0
                 U write@GLIBC_2.2.5
                 U writev@GLIBC_2.2.5

r? @bjorn3

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 12, 2026
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

let symbol = symbol.unwrap();
out.push((
String::from_utf8(symbol.name().to_vec()).unwrap(),
SymbolExportKind::Text,
Copy link
Member

Choose a reason for hiding this comment

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

We do need to distinguish between text and data symbols. Also on Windows I believe and on macOS I know we currently use the pre-C mangling names in exported_symbols. I think the post mangling name is fine here too for Windows, but you did need to check. On macOS however it is definitively not ok. The symbol names in the object file are prefixed with _, but the linker doesn't accept this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After testing, the symbol does have a prefix _ on macos, but not on windows. I have removed the prefix symbol (I don’t know why it was added back in the export_symbols function?)

Copy link
Member

Choose a reason for hiding this comment

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

64-bit Windows symbols do not use special mangling, but 32-bit symbols are prefixed with an additional leading underscore.

So:

int foo() { return 42; }

Would be foo symbol on 64-bit Windows, and _foo on 32-bit Windows.

Copy link
Member

Choose a reason for hiding this comment

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

And extern "stdcall" has extra mangling, right?

Copy link
Member

Choose a reason for hiding this comment

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

Not only that, all calling conventions have their own mangling: https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/name-decoration?view=msvc-170

I don't remember whether linkers can export symbols using .DEF files if the symbol doesn't exactly match calling convention. IIRC, GNU ld and LLD (not so sure about this one) can handle it, at least in some cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OMG. This is an area I'm unfamiliar with, and I don't have a 32-bit Windows device to test on. I'm unsure how to handle these symbols in 32-bit Windows; perhaps the linker will handle them correctly? Because I can't seem to find any special code in rustc that handles these symbols.

Copy link
Member

@mati865 mati865 Jan 16, 2026

Choose a reason for hiding this comment

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

You can test it on 64-bit Windows or any other system by cross-compiling to a i686 Windows target.

Anyway, once you add the test to this repo CI will be able to test it on all systems.

Copy link
Contributor Author

@cezarbbb cezarbbb Jan 19, 2026

Choose a reason for hiding this comment

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

I left a fixme, and I would like to provide the handling of 32-bit Windows as a future PR, is that ok?

@bjorn3
Copy link
Member

bjorn3 commented Jan 12, 2026

I think this is a reasonable approach. This will need a test though.

@JayanAXHF JayanAXHF added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 12, 2026
@cezarbbb
Copy link
Contributor Author

cezarbbb commented Jan 14, 2026

I think this is a reasonable approach. This will need a test though.

I've add a simple test.

@rustbot rustbot added the A-run-make Area: port run-make Makefiles to rmake.rs label Jan 19, 2026
@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot rustbot added the has-merge-commits PR has merge commits, merge with caution. label Jan 19, 2026
@rust-log-analyzer

This comment has been minimized.

@cezarbbb cezarbbb force-pushed the cstyle-export-rules2 branch from 0d2e81c to f4c91ab Compare January 19, 2026 08:07
@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot rustbot removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. has-merge-commits PR has merge commits, merge with caution. labels Jan 19, 2026
@cezarbbb cezarbbb force-pushed the cstyle-export-rules2 branch 2 times, most recently from def5d06 to 719e1b6 Compare January 19, 2026 08:24
@rustbot

This comment has been minimized.

@cezarbbb cezarbbb force-pushed the cstyle-export-rules2 branch from 3ecbcec to 4f948d8 Compare January 22, 2026 11:19
@rustbot
Copy link
Collaborator

rustbot commented Jan 22, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@cezarbbb cezarbbb changed the title export_c_static_library_symbols: export all global symbols from selected uptream c static libraries link modifier export-symbols: export all global symbols from selected uptream c static libraries Jan 23, 2026
@rust-log-analyzer

This comment has been minimized.

@cezarbbb
Copy link
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 23, 2026
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
pub lint_levels: CodegenLintLevels,
pub metadata_symbol: String,
pub exported_c_static_libraries: Vec<NativeLib>,
Copy link
Contributor

Choose a reason for hiding this comment

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

CrateInfo already has used_libraries (or native_libraries) which can be filtered by export_symbols: Some(true) in link.rs, this field shouldn't be necessary.

name: &str,
out: &mut Vec<(String, SymbolExportKind)>,
) -> io::Result<()> {
for search_path in sess.target_filesearch().search_paths(PathKind::Native) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The search should be done using find_native_static_library.

Ideally NativeLib::filename would be used, but it's currently set only for bundled libraries, and changing that may mess up other things.

@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants