-->

How can I set a custom C entry point with Clang on

2020-07-10 06:48发布

问题:

I have the following program:

#include <stdio.h>

int bob() {
    printf("bob\n");
    return 0;
}

int main() {
    printf("main\n");
    return 0;
}

On Linux, I can enable a custom entry point via:

gcc test.c -Wl,-e,bob

When I run the resulting program, I get:

./a.out
bob

On OS X, however, this doesn't work:

clang test.c -Wl,-e,bob
./a.out
main

I've tried everything to get this to work. I think it might be a bug. Here's the output with the -v option:

clang test.c -Wl,-e,bob -v

Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix
 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.9.0 -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name test.c -mrelocation-model pic -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 236.3 -v -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/5.1 -fdebug-compilation-dir /Users/mfichman/jogo -ferror-limit 19 -fmessage-length 125 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.9.0 -fencode-extended-block-signature -fdiagnostics-show-option -fcolor-diagnostics -vectorize-slp -o /var/folders/4z/q41by0256hjc7s6v8ljmfpw8lywh5g/T/test-9b80a6.o -x c test.c
clang -cc1 version 5.1 based upon LLVM 3.4svn default target x86_64-apple-darwin13.3.0
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/5.1/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /usr/include
 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)
End of search list.
 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.9.0 -e bob -o a.out /var/folders/4z/q41by0256hjc7s6v8ljmfpw8lywh5g/T/test-9b80a6.o -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/5.1/lib/darwin/libclang_rt.osx.a

You can see that clang is correctly passing -e to ld, so maybe this is a problem with Apple's ld. If that's the case, I'd be interested in workaround solutions.

回答1:

The default entry point overridden by the -e argument is not _main but rather start, which is responsible for setting up and calling _main, then passing the return value of _main to _exit. If you specify your own entry point you'll need to perform these steps yourself. There's currently no way to have this initialization performed for you but use a different main function as use of _main is hard-coded into the tools.

The reason your -e argument is ignored is due to a change in 10.8. Prior to this release the implementation of start was linked into each application via crt1.o. In 10.8 the start processing can be performed by dyld and the LC_MAIN load command specifies the offset to the main function within the program. Changing this offset appears to be what you want, but this is not currently possible as when the LC_MAIN startup method is used ld always uses _main and disregards the -e argument. To specify your own entry point you need to tell ld to use the old method of program startup, which you can do for an application with a deployment target of 10.8 or later by passing -no_new_main to the linker. This is the default behavior for applications with a deployment target earlier than 10.8.