Linker cannot find malloc and free on OS X

Jacob Carlborg via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Jun 5 06:05:09 PDT 2017


On 2017-06-05 13:48, bvoq wrote:

> So I ran: dmd -unittest -main -v -L-lgmp -L-lc -g gmp/*
> The error seems to stem from: cc dbgio.o -o dbgio -g -m64 -Xlinker
> -no_compact_unwind -lgmp -lc -L/usr/local/Cellar/dmd/2.074.0/lib -lgmp
> -lgmp -lgmp -lgmp -lc -lphobos2 -lpthread -lm
>
> Full invocation of command with verbose flag: cc dbgio.o -o dbgio -g
> -m64 -Xlinker -no_compact_unwind -lgmp -lc
> -L/usr/local/Cellar/dmd/2.074.0/lib -lgmp -lgmp -lgmp -lgmp -lc
> -lphobos2 -lpthread -lm -v
> gmp -lc -L/usr/local/Cellar/dmd/2.074.0/lib -lgmp -lgmp -lgmp -lgmp -lc
> -lphobos2 -lpthread -lm -v
> Apple LLVM version 8.1.0 (clang-802.0.42)
> Target: x86_64-apple-darwin16.7.0
> Thread model: posix
> InstalledDir:
> /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
>
>
> "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld"
> -demangle -lto_library
> /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libLTO.dylib
> -dynamic -arch x86_64 -macosx_version_min 10.12.0 -o dbgio
> -L/usr/local/Cellar/dmd/2.074.0/lib dbgio.o -no_compact_unwind -lgmp -lc
> -lgmp -lgmp -lgmp -lgmp -lc -lphobos2 -lpthread -lm -lSystem
> /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.1.0/lib/darwin/libclang_rt.osx.a
>
> Undefined symbols for architecture x86_64:
>   "free", referenced from:
>       _D3gmp1z3MpZ6__ctorMFNaNbNcNiNexAyakZS3gmp1z3MpZ in dbgio.o
>       _D3gmp1z3MpZ10fromStringMFNaNbNcNiNjNexAyakZS3gmp1z3MpZ in dbgio.o

I've managed to isolate and identified the problem. The problem is these 
two lines [1]:

pragma(mangle, "malloc") void* qualifiedMalloc(size_t size);
pragma(mangle, "free") void qualifiedFree(void* ptr);

On macOS all C symbols are mangled with an underscore prefix, meaning 
the "free" and "malloc" symbols are actually named _free and _malloc in 
the binary.

This is easy to verify by:

$ cat main.c
void foo();

int main()
{
     foo();
     return 0;
}

$ clang main.c
Undefined symbols for architecture x86_64:
   "_foo", referenced from:
       _main in main-8a6861.o

Here we can see that the linker is looking for the "_foo" symbol, while 
in your output it's looking for "free", without the underscore prefix.

When pragma(mangle) is used on an extern(C) symbol the compiler will 
automatically handle the prefixing of the symbol on macOS, making it 
line up with any C symbols.

Functions with D linkage have their own mangling, prefixed with _D, the 
fully qualified name mangled and the signature. It seems like that when 
using pragma(mangle) on function with D linkage the compiler will output 
the symbol exactly like it's specified in the source code, in 
pragma(mangle). This can be verified by:

$ cat main.d
void foo();

void main()
{
     foo();
}

$ dmd -c main.d
$ nm main.o | grep foo
U _D4main3fooFZv

And when using pragma(mangle):

$ cat main.d
pragma(mangle, "foo") void foo();

void main()
{
     foo();
}

$ dmd -c main.d
$ nm main.o | grep foo
U foo

No underscore prefix.

This happens to work on Linux because on Linux this mangling (with the 
underscore prefix) is not used for C symbols. But since the functions 
are not declared as extern(C) we're actually calling C functions using 
the D calling conventions, which just happens to work in this case 
because the C and D calling conventions are mostly the same.

[1] https://github.com/nordlow/gmp-d/blob/master/src/gmp/z.d#L1164-L1165

-- 
/Jacob Carlborg


More information about the Digitalmars-d-learn mailing list