zig icon indicating copy to clipboard operation
zig copied to clipboard

Allow exporting symbols from executable

Open codehz opened this issue 5 years ago • 22 comments

At least it is possible in linux, windows... (see ld.so) But zig just ignore the export and @export when build-exe

codehz avatar Oct 25 '20 06:10 codehz

That's not true. @export works in every output mode, you're probably using it wrong.

LemonBoy avatar Oct 25 '20 06:10 LemonBoy

@LemonBoy

export fn t() void {}

comptime {
@export(t, .{ .name="tx"});
}

pub fn main() void {}

command:

$ zig build-exe x.zig
$ nm -D x
nm: x: no symbols
$ objdump -T x

x:     file format elf64-x86-64

objdump: x: not a dynamic object
DYNAMIC SYMBOL TABLE:
no symbols

same thing happens in windows target

Image Size: 48000 Data dir: 00000000 00000000 (Export) Data dir: 0003E977 0000003C (Import) Data dir: 00000000 00000000 (Resource)

PS: It works if i export symbols from c (dllexport)

codehz avatar Oct 25 '20 06:10 codehz

@codehz you created a static executable; use zig build-exe -dynamic to create a dynamic executable.

Edit: uhh; is -dynamic broken when not linking against anything?

daurnimator avatar Oct 25 '20 07:10 daurnimator

use zig build-exe -dynamic to create a dynamic executable.

no effect at all, and in windows, there is no dynamic executable

codehz avatar Oct 25 '20 07:10 codehz

no effect at all

yes, see my edit above: possible workaround is linking libc -lc as well.

daurnimator avatar Oct 25 '20 07:10 daurnimator

possible workaround is linking libc -lc as well.

nope, I can build it without -lc, and adding -lc has not make t and tx exported

x:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __libc_start_main
0000000000000000  w   D  *UND*  0000000000000000  Base        __gmon_start__
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __errno_location
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.4   __stack_chk_fail
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3   __tls_get_addr
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 abort
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 close
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 dl_iterate_phdr
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 environ
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 flock
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 getenv
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 isatty
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.14  memcpy
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 memset
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 mmap
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 munmap
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.4   openat
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 read
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 sched_yield
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 sigaction
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 write
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __fxstat

codehz avatar Oct 25 '20 07:10 codehz

Here's your exported symbol:

zig build-exe x.zig
readelf -s foo |& grep tx

If you want to have your symbols exported in the dynamic symbol table:

zig build-exe -rdynamic x.zig
objdump -T foo | grep tx

You're welcome.

LemonBoy avatar Oct 25 '20 08:10 LemonBoy

exported in the dynamic symbol table:

Unfortunately, the binary produced by this method cannot be loaded by dlopen ./x: cannot dynamically load executable and I also tried this for target x86_64-windows-gnu, not working either

codehz avatar Oct 25 '20 13:10 codehz

Unfortunately, the binary produced by this method cannot be loaded by dlopen

Because it's a binary and not a shared library? This is starting to sound a lot like a XY problem, do you mind explaining what are you trying to do and what have you tried?

LemonBoy avatar Oct 25 '20 15:10 LemonBoy

@LemonBoy Ok, now the origin problem is I want to do this on windows: let plugin (dll) to load symbol from exe, it has been tested in a plain c project

  1. start Main.exe
  2. main.exe load plugin dll (at runtime, so no circular dependency)
  3. plugin can call exported function from main exe

(Yes, technically speaking, this is not the best method, the "correct" method is let the main program initialize plugin and provides an interface.)

codehz avatar Oct 26 '20 07:10 codehz

Heya @codehz!

I did this as well at work and i now figured that i'm in devils kitchen. This approach is easy and convenient, but will make your life horrible as soon as you ever want to rename your executable. Because then you have to recompile all plugins, every time you change the executable name. And you cannot create or deploy staging/testing builds, as you always have to overwrite your production executable (Imagine you have System.exe in production, you want to test if your changes to an API were successful, so you deploy System.fixed.exe. But your plugins will still load and call System.exe instead.)

But still, this should be a possible use case to compile LoadLibrary-loadable executables

ikskuh avatar Oct 26 '20 08:10 ikskuh

@codehz it sounds like you're looking for the zig equivalent of -Wl,-E; I think that's only a feature of dynamic linked ELF executables? I'm not sure if PE executables can do that: the ld flag --export-all-symbols seems to only be supported for DLLs, not executables?

daurnimator avatar Oct 26 '20 08:10 daurnimator

I'm not sure if PE executables can do that: the ld flag --export-all-symbols seems to only be supported for DLLs, not executables?

I just simply add __declspec(dllexport) in c source, and it work like a charm..

codehz avatar Oct 26 '20 08:10 codehz

I just simply add __declspec(dllexport) in c source, and it work like a charm..

Then -fdll-export-fns is your friend, it marks all the exported declarations as dllexport. I'm no Windows expert but this all or nothing option isn't granular enough, what about an extra field in the @export options?

LemonBoy avatar Oct 26 '20 09:10 LemonBoy

What is the actual issue here? I've read through the discussion and I'm honestly quite confused.

alexrp avatar Jun 22 '24 07:06 alexrp

I think this is because zig does not support -Wl,-E. In C language, the executable file compiled with -Wl,-E flag contains symbols.

hanxi avatar Aug 16 '24 11:08 hanxi

The -rdynamic C compiler flag, as mentioned by @LemonBoy above, passes -E to the linker - i.e. it is equivalent to -Wl,-E.

alexrp avatar Aug 16 '24 11:08 alexrp

I try test this. https://github.com/brickBrackBro/lua/blob/main/build.zig

zig build -Dshared=true will generate lua and lua.so file. the symbols are in lua.so file.

zig build will only generate one lua file and no symbols.

hanxi avatar Aug 16 '24 11:08 hanxi

zig build -Dshared=true will generate lua and lua.so file. the symbols are in lua.so file.

zig build will only generate one lua file and no symbols.

Well, yeah, I don't see you passing -rdynamic anywhere in that build script. So the behavior is as expected.

alexrp avatar Aug 16 '24 11:08 alexrp

zig build -Dshared=true will generate lua and lua.so file. the symbols are in lua.so file. zig build will only generate one lua file and no symbols.

Well, yeah, I don't see you passing -rdynamic anywhere in that build script. So the behavior is as expected.

I don't know where to set -rdynamic in build.zig file. Can you give me some suggest. Thanks.

hanxi avatar Aug 16 '24 13:08 hanxi

std.Build.Step.Compile has an rdynamic field that you can set.

alexrp avatar Aug 16 '24 13:08 alexrp

std.Build.Step.Compile has an rdynamic field that you can set.

Nice job! Your solution is great and solved my problem. Thank you very much for your help.

hanxi avatar Aug 16 '24 14:08 hanxi

I'm going to close this as I don't think there's a Zig bug here, but it's honestly a bit confusing to decode this issue.

If I'm wrong, please comment with a clear explanation and I'll reopen.

alexrp avatar Oct 02 '24 22:10 alexrp