Skip to content

Staticlib hide internal symbols#155338

Open
cezarbbb wants to merge 1 commit into
rust-lang:mainfrom
cezarbbb:staticlib-symbol-hygiene
Open

Staticlib hide internal symbols#155338
cezarbbb wants to merge 1 commit into
rust-lang:mainfrom
cezarbbb:staticlib-symbol-hygiene

Conversation

@cezarbbb
Copy link
Copy Markdown
Contributor

@cezarbbb cezarbbb commented Apr 15, 2026

View all comments

According to issue #104707, when building a staticlib, all Rust internal symbols — mangled symbols, #[rustc_std_internal_symbol] items, allocator shims, etc. — leak out of the static archive. In contrast, cdylib correctly exports only #[no_mangle] symbols via a linker version script.

-Zstaticlib-hide-internal-symbols directly post-processes ELF object files in the archive: parsing the SHT_SYMTAB sections and setting STV_HIDDEN visibility on any GLOBAL/WEAK defined symbol that is not in the exported symbol set, without changing the binding. This is an in-place modification (only writing the st_other byte per matching entry), with zero overhead.

Supported on ELF targets (Linux, BSD, etc.) and Apple targets (macOS, iOS, etc.). On unsupported targets (Windows), a warning is emitted and the flag has no effect.

Update: The rename counterpart (-Zstaticlib-rename-internal-symbols) is in #156950.

The test code are as follows:

1.a std rust staticlib:

use std::collections::HashMap;
use std::panic::{catch_unwind, AssertUnwindSafe};

#[no_mangle]
pub extern "C" fn my_add(a: i32, b: i32) -> i32 { a + b }

#[no_mangle]
pub extern "C" fn my_hash_lookup(key: u64) -> u64 {
    let mut map = HashMap::new();
    for i in 0..100u64 { map.insert(i, i.wrapping_mul(2654435761)); }
    *map.get(&key).unwrap_or(&0)
}

pub fn internal_reverse(s: &str) -> String { s.chars().rev().collect() }

#[no_mangle]
pub extern "C" fn my_format_number(n: i32) -> i32 {
    let s = format!("number: {}", n); s.len() as i32
}

#[no_mangle]
pub extern "C" fn my_safe_div(a: i32, b: i32) -> i32 {
    match catch_unwind(AssertUnwindSafe(|| {
        if b == 0 { panic!("division by zero!"); }
        a / b
    })) {
        Ok(result) => result,
        Err(_) => -1,
    }
}

#[no_mangle]
pub extern "C" fn my_uncaught_panic() { panic!("uncaught panic across FFI"); }

1.b downstream c program:

extern int my_add(int a, int b);
extern unsigned long my_hash_lookup(unsigned long key);
extern int my_format_number(int n);
extern int my_safe_div(int a, int b);
extern void my_uncaught_panic(void);

int main() {
    int failures = 0;
    if (my_add(10, 20) != 30) failures++;
    if (my_hash_lookup(5) != 5UL * 2654435761UL) failures++;
    if (my_format_number(42) != 10) failures++;
    if (my_safe_div(100, 5) != 20) failures++;
    if (my_safe_div(100, 0) != -1) failures++;
    pid_t pid = fork();
    if (pid == 0) { alarm(5); my_uncaught_panic(); _exit(0); }
    else { waitpid(pid, &status, 0); }
    return failures;
}

The test results with different compiler flags(which might cause binary size reduction) are as follows:
1.c result with -Zstaticlib-hide-internal-symbols

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 1.7M      1.5M  204K (12%)    1735       5    1730
  lto_thin                616K      584K  33K (5%)     246       5     241
  lto_fat                 525K      525K    0 (0%)       6       5       1
  opt_s                   1.7M      1.5M  204K (12%)    1735       5    1730
  opt_z                   1.7M      1.5M  204K (12%)    1735       5    1730
  lto_thin_z              602K      570K  32K (5%)     246       5     241
  lto_fat_z               514K      514K    0 (0%)       6       5       1
  full                    514K      514K    0 (0%)       6       5       1

1.d result with -Zstaticlib-hide-internal-symbols + -Zstaticlib-rename-internal-symbols

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 1.7M      1.5M  162K (9%)    1735       5    1730
  lto_thin                616K      599K  18K (2%)     246       5     241
  lto_fat                 525K      535K  -1% (-1%)       6       5       1
  opt_s                   1.7M      1.5M  162K (9%)    1735       5    1730
  opt_z                   1.7M      1.5M  162K (9%)    1735       5    1730
  lto_thin_z              602K      585K  18K (2%)     246       5     241
  lto_fat_z               514K      524K  -1% (-1%)       6       5       1
  full                    514K      523K  -1% (-1%)       6       5       1

2.a no_std rust staticlib

#![no_std]
#![feature(core_intrinsics)]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! { loop {} }

#[no_mangle]
pub extern "C" fn embedded_add(a: i32, b: i32) -> i32 { a.wrapping_add(b) }

#[no_mangle]
pub extern "C" fn embedded_checksum(data: *const u8, len: usize) -> u8 {
    if data.is_null() { return 0; }
    let slice = unsafe { core::slice::from_raw_parts(data, len) };
    let mut sum: u8 = 0;
    for &byte in slice { sum = sum.wrapping_add(byte); }
    sum
}

fn internal_helper() -> i32 { 42 }
#[no_mangle]
pub extern "C" fn call_internal() -> i32 { internal_helper() }

#[no_mangle]
pub extern "C" fn embedded_trigger_abort() { core::intrinsics::abort(); }

2.b downstream c program

extern int embedded_add(int a, int b);
extern unsigned char embedded_checksum(const unsigned char *data, unsigned long len);
extern int call_internal(void);
extern void embedded_trigger_abort(void);

int main() {
    int failures = 0;
    if (embedded_add(10, 20) != 30) failures++;
    unsigned char data[] = {1, 2, 3};
    if (embedded_checksum(data, 3) != 6) failures++;
    if (call_internal() != 42) failures++;
    pid_t pid = fork();
    if (pid == 0) { embedded_trigger_abort(); _exit(0); }
    else { waitpid(pid, &status, 0); }
    return failures;
}

The test results with different compiler flags(which might cause binary size reduction) are as follows:
2.c result with -Zstaticlib-hide-internal-symbols

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 485K      429K  56K (11%)     490       4     486
  lto_thin                180K      180K    0 (0%)       4       4       0
  lto_fat                 179K      179K    0 (0%)       4       4       0
  opt_s                   485K      429K  56K (11%)     490       4     486
  opt_z                   485K      429K  56K (11%)     490       4     486
  lto_thin_z              180K      180K    0 (0%)       4       4       0
  lto_fat_z               179K      179K    0 (0%)       4       4       0
  full                    179K      179K    0 (0%)       4       4       0

2.d result with -Zstaticlib-hide-internal-symbols + -Zstaticlib-rename-internal-symbols

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 485K      447K  39K (7%)     490       4     486
  lto_thin                180K      189K  -5% (-5%)       4       4       0
  lto_fat                 179K      189K  -5% (-5%)       4       4       0
  opt_s                   485K      448K  38K (7%)     490       4     486
  opt_z                   485K      448K  38K (7%)     490       4     486
  lto_thin_z              180K      189K  -5% (-5%)       4       4       0
  lto_fat_z               179K      189K  -5% (-5%)       4       4       0
  full                    179K      189K  -5% (-5%)       4       4       0

Test results show that this compiler option is beneficial for scenarios where LTO cannot be enabled.

r? @bjorn3 @petrochenkov

@rustbot rustbot added 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-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 Apr 15, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 15, 2026

r? @petrochenkov

rustbot has assigned @petrochenkov.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: codegen, compiler
  • codegen, compiler expanded to 69 candidates
  • Random selection from 16 candidates

@rustbot

This comment has been minimized.

@rustbot rustbot assigned bjorn3 and unassigned petrochenkov Apr 15, 2026
@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 15, 2026

This would also need to rename symbols to avoid conflicts between two rust staticlibs ending up getting linked together, right?

@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 15, 2026

The rust_eh_personality symbol is always kept visible to ensure .eh_frame unwinding works correctly for C consumers.

Why exactly is that the case? rust_eh_personality is actually the symbol that is most likely to cause conflicts as it is the only one whose name doesn't get mangled depending on the rustc version.

@cezarbbb cezarbbb force-pushed the staticlib-symbol-hygiene branch from ff707ad to 7ac49d1 Compare April 15, 2026 12:35
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

This would also need to rename symbols to avoid conflicts between two rust staticlibs ending up getting linked together, right?

My primary goal right now is to reduce binary size, so I don't have immediate plans to implement symbol renaming. This means that linking multiple Rust staticlibs together can still result in multiple definition errors. Would you like me to address that in this PR as well? It seems feasible to implement — for example, by rehashing symbols and updating their references accordingly.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

The rust_eh_personality symbol is always kept visible to ensure .eh_frame unwinding works correctly for C consumers.

Why exactly is that the case? rust_eh_personality is actually the symbol that is most likely to cause conflicts as it is the only one whose name doesn't get mangled depending on the rustc version.

I previously assumed this symbol needed to remain externally visible to support scenarios requiring cross-language exception propagation. Do you think we should also set rust_eh_personality as hidden?

@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 15, 2026

If it isn't too hard it would be nice to do symbol renaming too. I think doing in-place modification isn't going to work for that though. Adding a unique suffix would require growing the size of the string table.

@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 15, 2026

I previously assumed this symbol needed to remain externally visible to support scenarios requiring cross-language exception propagation. Do you think we should also set rust_eh_personality as hidden?

rust_eh_personality is only meant to be referenced by the .eh_frame section of rust object files. The only reason it's name isn't mangled is because LLVM hard codes the name to determine the exception table format to emit.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

If it isn't too hard it would be nice to do symbol renaming too. I think doing in-place modification isn't going to work for that though. Adding a unique suffix would require growing the size of the string table.

Got it. I will first fix the rust_eh_personality issue, and then try to implement symbol renaming.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@cezarbbb cezarbbb force-pushed the staticlib-symbol-hygiene branch from 5e1c3a1 to c7d4e98 Compare April 16, 2026 03:27
@SparrowLii
Copy link
Copy Markdown
Member

@bors delegate=try

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 16, 2026

✌️ @cezarbbb, you can now perform try builds on this pull request!

You can now post @bors try to start a try build.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

@bors try

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Apr 16, 2026
`-Zstaticlib-hide-internal-symbols`: Hide non-exported internal symbols from staticlibs
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 16, 2026

☀️ Try build successful (CI)
Build commit: a9431d3 (a9431d37da1d0346038257cec9d94f2783997621, parent: e8e4541ff19649d95afab52fdde2c2eaa6829965)

@cezarbbb
Copy link
Copy Markdown
Contributor Author

@bors try jobs=x86_64-*

@rust-bors

This comment has been minimized.

@MicroDroid
Copy link
Copy Markdown

MicroDroid commented May 14, 2026

Preliminarily speaking, I think it is renaming user-defined symbols, causing undefined symbol errors when the output goes into the linking stage:

ld.lld: error: undefined symbol: rust::cxxbridge1::String::String(char const*)
>>> referenced by READACTEDClient.cpp:89 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/READACTEDClient.cpp:89)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a

ld.lld: error: undefined symbol: READACTEDBridge::generateKeyPackage(READACTEDBridge::GenerateKeyPackageInput)
>>> referenced by READACTEDClient.cpp:88 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/READACTEDClient.cpp:88)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a

ld.lld: error: undefined symbol: rust::cxxbridge1::String::~String()
>>> referenced by READACTEDRustBridge.h:108 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/include/READACTEDRustBridge.h:108)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a
>>> referenced by READACTEDRustBridge.h:99 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/include/READACTEDRustBridge.h:99)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a
>>> referenced by READACTEDRustBridge.h:99 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/include/READACTEDRustBridge.h:99)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

(I am using cxx.rs btw)

Simply toggling the rename flag off fixes this build error.

Still investigating.

@MicroDroid
Copy link
Copy Markdown

I think the rename flag indeed modifies public symbols:

$ nm -g --demangle without-rename-flag/libmls_rust.a 2>/dev/null | grep REDACTED

0000000000000000 T _REDACTEDBridge$cxxbridge1$190$generateKeyPackage
                 U _REDACTEDBridge$cxxbridge1$190$generateKeyPackage
0000000000000000 T REDACTEDBridge::generateKeyPackage(REDACTEDBridge::GenerateKeyPackageInput)

$ nm -g --demangle with-rename-flag/libmls_rust.a 2>/dev/null | grep REDACTED

0000000000000000 T _REDACTEDBridge$cxxbridge1$190$generateKeyPackage
                 U _REDACTEDBridge$cxxbridge1$190$generateKeyPackage
0000000000000000 T __ZN9REDACTEDBridge18generateKeyPackageENS_23GenerateKeyPackageInputE_rse4eba72a7f00581d

When linking against without-rename-flag/libmls_rust.a, REDACTEDBridge::generateKeyPackage(REDACTEDBridge::GenerateKeyPackageInput) is found but when linking against with-rename-flag/libmls_rust.a, it isn't.

It also seems like the flag breaks mangling somehow as such it could demangle REDACTEDBridge::generateKeyPackage(REDACTEDBridge::GenerateKeyPackageInput) but it failed to demangle __ZN9REDACTEDBridge18generateKeyPackageENS_23GenerateKeyPackageInputE_rse4eba72a7f00581d, although it seems like the linker doesn't particularly complain about this.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

I see. The rename logic processed all .o files in the archive, including C/C++ .o files from native libraries. These native symbols were not in exported_symbols, so they were incorrectly renamed.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

I think I can filter by filename and only process .rcgu.o files (there should be no exceptions this way?).

@MicroDroid
Copy link
Copy Markdown

I have no idea, but let me test that already on my setup

@MicroDroid
Copy link
Copy Markdown

I think I'm like 99% sure renaming works flawlessly now.

So my setup was 2 Rust libraries being ported to C++ via cxx.rs and linked independently into a mobile app.

There were duplicate symbol errors, with 2 categories of symbols being duplicate:

  • cxx.rs's own symbols, but I wrote a script to rename those
  • Rust stdlib symbols

For one of the Rust libraries I built it with the -Zstaticlib-rename-internal-symbols flag and then ran the output through the script I wrote to process cxx.rs symbols, and then I built the mobile app and it just built without any issues.

That was for Android though, for iOS I'll get that tested very soon too, maybe within the next hour.

@MicroDroid
Copy link
Copy Markdown

Took me long time to test for iOS cause I'm having other unrelated issues with the iOS build, but nonetheless judging by how far I am I think the patch just works on iOS too ✅

@petrochenkov
Copy link
Copy Markdown
Contributor

@cezarbbb asked me to take over the review since @bjorn3 didn't respond for some time.
I'll review this, then return the PR back to Bjorn, and then merge in a ~week if there's no concerns.

r? @petrochenkov
@rustbot ready

@rustbot rustbot assigned petrochenkov and unassigned bjorn3 May 22, 2026
@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 May 22, 2026
@petrochenkov
Copy link
Copy Markdown
Contributor

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 1.7M      1.5M  204K (12%)    1735       5    1730

What do the numbers in the tables mean?

  • 1.7MB is a size of what exactly?
  • What does -Zsave mean (or rather why is it called -Zsave)
  • What are ALL, OFF.dynsym and ON.dynsym?

@petrochenkov
Copy link
Copy Markdown
Contributor

-Zstaticlib-hide-internal-symbols and -Zstaticlib-rename-internal-symbols are two different features with different goals.
Could you split this work into 2 PRs (starting with symbol hiding)?
This way we'll make progress on landing this faster.

# `staticlib-hide-internal-symbols`

When building a `staticlib`, this option hides all non-exported Rust-internal
symbols by setting their ELF visibility to `STV_HIDDEN`.
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 22, 2026

Choose a reason for hiding this comment

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

What is the difference with -Z default-visibility=hidden here?
As far as I can see, that option will also set visibility to hidden for all SymbolExportLevel::Rust symbols.

View changes since the review

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.

-Z default-visibility=hidden only affects the current crate's codegen. A staticlib also bundles .o files from upstream crates (std, core, etc.) that were compiled without it. -Zstaticlib-hide-internal-symbols post-processes the entire archive including those pre-compiled upstream objects.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you add this comparison with -Z default-visibility=hidden to the documentation?

Comment thread src/doc/unstable-book/src/compiler-flags/staticlib-rename-internal-symbols.md Outdated
Comment thread tests/run-make/staticlib-hide-internal-symbols-macho/lib.rs Outdated
Comment thread compiler/rustc_codegen_ssa/src/back/link.rs Outdated
Comment thread src/doc/unstable-book/src/compiler-flags/staticlib-rename-internal-symbols.md Outdated
Comment thread tests/ui/README.md Outdated
@petrochenkov
Copy link
Copy Markdown
Contributor

(I started reviewing, will continue on Monday.)

@cezarbbb
Copy link
Copy Markdown
Contributor Author

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 1.7M      1.5M  204K (12%)    1735       5    1730

What do the numbers in the tables mean?

  • 1.7MB is a size of what exactly?
  • What does -Zsave mean (or rather why is it called -Zsave)
  • What are ALL, OFF.dynsym and ON.dynsym?

Sorry for the confusing column names. Here's what the table shows:

The test links the staticlib into a shared library using --whole-archive, then measures the resulting .so size and counts exported symbols via llvm-nm -D | grep ' T '.

OFF.so file size when built without the flag
ON.so file size when built with the flag
-Zsave — size reduction (OFF - ON), poorly named, it just means "savings from -Z"
ALL — number of GLOBAL text symbols in .dynsym without the flag (everything is exported)
OFF.dynsym — number of GLOBAL text symbols in .dynsym with the flag (only #[no_mangle] exports remain)
ON.dynsym — number of symbols that got hidden (ALL - OFF.dynsym)
So for the default row: without the flag all 1735 symbols are exported; with the flag only 5 remain visible (the actual public API), and 1730 internal symbols got hidden.

The column names are bad — I'll rewrite the table with clearer labels when I update the PR description.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

-Zstaticlib-hide-internal-symbols and -Zstaticlib-rename-internal-symbols are two different features with different goals. Could you split this work into 2 PRs (starting with symbol hiding)? This way we'll make progress on landing this faster.

Makes sense, I'll split it.

Comment thread compiler/rustc_codegen_ssa/src/back/archive.rs Outdated
@cezarbbb cezarbbb force-pushed the staticlib-symbol-hygiene branch from 352adb2 to 786373a Compare May 25, 2026 04:41
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 25, 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.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

Working on splitting this pull request, and it seems some functions will be reused. Clarifying the logic.

@cezarbbb cezarbbb force-pushed the staticlib-symbol-hygiene branch from 786373a to 40c254b Compare May 26, 2026 03:38
@cezarbbb cezarbbb changed the title -Zstaticlib-hide-internal-symbols and Zstaticlib-rename-internal-symbols: hide/rename internal symbols in staticlibs Staticlib hide internal symbols May 26, 2026
@rust-log-analyzer

This comment has been minimized.

@cezarbbb cezarbbb force-pushed the staticlib-symbol-hygiene branch from 40c254b to 54a7c4c Compare May 26, 2026 03:47
@petrochenkov
Copy link
Copy Markdown
Contributor

The column names are bad — I'll rewrite the table with clearer labels when I update the PR description.

Yes, could you put the legend from #155338 (comment) into the PR description before the tables as well.


use std::collections::HashSet;

use run_make_support::object::Endianness;
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 26, 2026

Choose a reason for hiding this comment

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

Suggested change
use run_make_support::object::Endianness;
use run_make_support::object::{elf, Endianness};

There are many uses of elf::something below, let's clean them up.

View changes since the review


for member in archive.members() {
let member = member.unwrap();
let member_name = std::str::from_utf8(member.name()).unwrap();
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 26, 2026

Choose a reason for hiding this comment

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

Suggested change
let member_name = std::str::from_utf8(member.name()).unwrap();
let member_name = str::from_utf8(member.name()).unwrap();

View changes since the review

) -> Option<&'data str> {
let bytes = strtab.get(symbol.st_name(endian)).ok()?;
let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
std::str::from_utf8(&bytes[..end]).ok()
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 26, 2026

Choose a reason for hiding this comment

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

Suggested change
std::str::from_utf8(&bytes[..end]).ok()
str::from_utf8(&bytes[..end]).ok()

View changes since the review


fn visibility_name(v: u8) -> &'static str {
match v {
v if v == object::elf::STV_DEFAULT => "STV_DEFAULT",
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 26, 2026

Choose a reason for hiding this comment

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

Suggested change
v if v == object::elf::STV_DEFAULT => "STV_DEFAULT",
elf::STV_DEFAULT => "STV_DEFAULT",

Can't you match on these directly?

View changes since the review

for member in archive.members() {
let member = member.unwrap();
let member_name = std::str::from_utf8(member.name()).unwrap();
if !member_name.ends_with(".rcgu.o") {
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 26, 2026

Choose a reason for hiding this comment

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

Suggested change
if !member_name.ends_with(".rcgu.o") {
if !member.name().ends_with(b".rcgu.o") {

will probably work too, slices support ends_with.

View changes since the review

let bind = symbol.st_bind();
let shndx = symbol.st_shndx(endian);

if shndx == object::elf::SHN_UNDEF as u16 {
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 26, 2026

Choose a reason for hiding this comment

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

Suggested change
if shndx == object::elf::SHN_UNDEF as u16 {
if shndx == object::elf::SHN_UNDEF {

View changes since the review

}
}

fn read_symbol_name<'data>(
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 26, 2026

Choose a reason for hiding this comment

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

Doesn't symbol.name() just work?
I see other tests using it.

View changes since the review

v if v == object::elf::STV_PROTECTED => "STV_PROTECTED",
_ => "UNKNOWN",
}
}
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 26, 2026

Choose a reason for hiding this comment

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

Most comments from this file basically apply to tests/run-make/staticlib-hide-internal-symbols-macho/rmake.rs too.

View changes since the review

} else if let Some(symbols) = crate_info.exported_symbols.get(&CrateType::StaticLib) {
use rustc_data_structures::fx::FxHashSet;
let keep: FxHashSet<String> = symbols.iter().map(|(s, _)| s.clone()).collect();
ab.set_hide_symbols(keep);
Copy link
Copy Markdown
Contributor

@petrochenkov petrochenkov May 26, 2026

Choose a reason for hiding this comment

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

Suggested change
ab.set_hide_symbols(keep);
ab.set_hide_symbols(symbols.iter().map(|(s, _)| s.clone()).collect());

View changes since the review

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

Labels

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-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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants