Skip to content

Fix for #1878. 'zig init-lib' on MacOS missing __mh_execute_header #1903

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

Closed
wants to merge 2 commits into from
Closed

Fix for #1878. 'zig init-lib' on MacOS missing __mh_execute_header #1903

wants to merge 2 commits into from

Conversation

wilsonk
Copy link
Contributor

@wilsonk wilsonk commented Jan 31, 2019

This workaround is also found in the 'shared-library' example with a TODO to remove it. Hopefully this can be used as a quick fix so that new users don't run into an obscure error with init-lib. Apparently, libSystem doesn't define this symbol.

I think that the __mh_execute_header symbol is supposed to only be in actual executable files, however, during Zigs compilation of the init-lib/src/main.zig file on MacOS, the std/c/darwin.zig file declares this symbol as an external "C" symbol...then I think std/debug/index.zig uses this symbol to set up a base address and offset for debug info. The act of linking the .o file into a library is where 'init-lib' actually fails.

I assume that this symbol should not be used for .o files and should only be inserted/used when linking an executable and not a library?

I can look further into it if someone else doesn't know of a fix for this? :)

@andrewrk
Copy link
Member

Thank you for making this pull request. When investigating this, I found and reported #1981 and #1982. However using the workaround mentioned in #1981 I was able to verify a strategy that will resolve this __mh_execut_header problem in a satisfying way:

const std = @import("std");
export fn base_address() usize {
    return std.os.getBaseAddress();
}

var _mh_execute_header = extern struct {
    x: usize,
}{ .x = 0 };

comptime {
    const builtin = @import("builtin");
    @export("__mh_execute_header", _mh_execute_header, builtin.GlobalLinkage.Weak);
}
#include <stdio.h>

size_t base_address(void);

int main(int argc, char **argv) {
    fprintf(stderr, "base=%zu\n", base_address());
}
$ zig build-obj lib.zig
$ libtool -static -o lib.a lib.o
$ cc -o test test.c lib.a
$ ./test
base=4395230920

So you can see that, at least in static libs, __mh_execute_header works as desired as a weak external symbol. When I linked as a dynamic lib, the executable crashed at runtime with a dynamic loader error:

$ libtool -dynamic -o lib.so lib.o -lSystem -macosx_version_min 10.10
$ cc -o test test.c lib.so
$ ./test
dyld: __dyld section not supported in lib.so
Abort trap: 6

I consider this part of #1982. Anyway, I think it's still clear that the best solution to this is to move this code from userland to the compiler:

var _mh_execute_header = extern struct {
    x: usize,
}{ .x = 0 };

comptime {
    const builtin = @import("builtin");
    if (builtin.os == builtin.Os.macosx) {
        @export("__mh_execute_header", _mh_execute_header, builtin.GlobalLinkage.Weak);
    }
}

...which I'm about to do right now.

@andrewrk
Copy link
Member

Actually, even better idea: just put that code next to the part that references the symbol.

@andrewrk andrewrk closed this in 28bf768 Feb 18, 2019
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

Successfully merging this pull request may close these issues.

2 participants