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

-fstrip removes exported symbols when building executable #22339

Open
noctice007 opened this issue Dec 28, 2024 · 7 comments
Open

-fstrip removes exported symbols when building executable #22339

noctice007 opened this issue Dec 28, 2024 · 7 comments

Comments

@noctice007
Copy link

Summary

When using the -fstrip flag with zig build-exe, the exported symbols are removed from the resulting binary, which seems unexpected.

Steps to Reproduce

  1. Create a file main.zig with the following content:
    export fn foo() void {}
    pub fn main() void {}
  2. Run the following command:
    zig build-exe main.zig -fstrip
    
  3. Attempt to disassemble the foo function in the resulting binary:
    objdump main --disassemble=foo
    

Observed Behavior

Output

main:     file format elf64-x86-64


Disassembly of section .text:
<blank>

The foo section is not found, indicating that the -fstrip flag removed the exported symbol.

Expected Behavior

The foo function, being explicitly marked as export, should remain accessible in the binary, even when -fstrip is used

Environment

  • Zig version: 0.13.0
  • OS: Arch linux x86_64

Additional Note

If this behavior is intentional, clarification in the documentation would be helpful. If not, this might be a bug with -fstrip implementation.

@alexrp
Copy link
Member

alexrp commented Dec 28, 2024

You probably want -rdynamic.

@noctice007
Copy link
Author

You probably want -rdynamic.

I'm not an expert in low level and assembly output generation
but adding -rdynamic increases the size of the executable to 161K from 8.2K in my machine
The base command is:

zig build-exe main.zig -OReleaseFast -fstrip -fsingle-threaded

This gives the smaller size version of the executable
Is this the wanted behavior?

@alexrp
Copy link
Member

alexrp commented Dec 28, 2024

Well, what exactly is your goal? It normally doesn't make a ton of sense to export a function from an executable, which is why you have to opt into it with -rdynamic, and why -fstrip happily strips that symbol name by default (the symbol name is considered useless, strippable data if it's not exported by way of -rdynamic).

@noctice007
Copy link
Author

Thanks for the explanation. I get that exporting functions from an executable isn’t a common thing and that using -rdynamic is the intentional way to opt into it. Still, the increase in size from -rdynamic feels a bit off, especially since small binary sizes is one of Zig selling point.

In cases where you really need to export just one or two functions, it feels like the current approach punishes that use case by adding unnecessary bloat. I get that -fstrip is doing what it’s supposed to, but the trade-off here feels a little inconvenient when the goal is keeping the binary lean while still exporting something essential.

I get it if this is just how it’s designed to work, but it feels like a tricky spot for people in this specific situation.

@alexrp
Copy link
Member

alexrp commented Dec 28, 2024

To be clear, we only advertise small binary sizes for -O ReleaseSmall. I'm not completely sure what the size increase here is coming from; that needs investigating. It does look suspect.

The good news, though, is that if you use -lc (which you probably should if you're expecting to use dynamic linking), then the size increase from -O ReleaseSmall -fstrip -lc to -O ReleaseSmall -fstrip -lc -rdynamic is just 4.9K to 5.3K.

@noctice007
Copy link
Author

what does -lc do
I haven't found the documentation for it in both zig build-exe --help and zig build-lib --help

@Rexicon226
Copy link
Contributor

what does -lc do

It links libc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants