Search code examples
windowsvisual-c++linkerobject-files

Removing symbols from object file on windows


Is there any way to remove(or make local) symbols in an object file? I'm looking for something like objcopy --keep-global-symbol on linux.

Or maybe there is a way to tell linker which symbols should be hidden? I found this page: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx which describes .Def files and my impression from the reading is that I can use these files not only for dll's but also for static libraries. Is this true?

I need this, because I link with 2 libraries A and B which export the same symbols. A is linked dynamically and B is linked statically. If a symbols is exported both by A and B I want my app to use symbol from A, plus I want to use some symbols from B (which are only in B).


Solution

  • If you install one of the Mingw GCC ports, e.g. mingw-w64, then you will also get the ports of binutils for Windows PE binaries and you will be able to use the familar objcopy --keep-global-symbol.

    Find it in the bin directory of your chosen installation, e.g. C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev0\mingw64\bin

    However...

    You may well have an XY problem here, because the linker will resolve a symbol from the first library in the input sequence that defines it and ignore definitions in later libraries; so you may be able to give preference to the definitions from the DLL just by linking it before the static library. An illustration:

    foo_static.c

    #include <stdio.h>
    
    void foo(void)
    {
        puts("foo_static");
    }
    

    bar_static.c

    #include <stdio.h>
    
    void bar(void)
    {
        puts("bar_static");
    }
    

    foo_dynamic.c

    #include <stdio.h>
    
    __declspec(dllexport) void foo(void)
    {
        puts("foo_dynamic");
    }
    

    gum_dynamic.c

    #include <stdio.h>
    
    __declspec(dllexport) void gum(void)
    {
        puts("gum_dynamic");
    }
    

    Compile the *_static.c source files and archive the object files in a static library static.lib:

    >cl -c *_static.c
    Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    bar_static.c
    foo_static.c
    Generating Code...
    
    >lib -out:static.lib *_static.obj
    Microsoft (R) Library Manager Version 14.11.25547.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    

    Compile the *_dynamic.c source files and link the object files in a DLL dynamic.dll:

    >cl -c *_dynamic.c
    Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    foo_dynamic.c
    gum_dynamic.c
    Generating Code...
    
    >link -dll -out:dynamic.dll *_dynamic.obj
    Microsoft (R) Incremental Linker Version 14.11.25547.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
       Creating library dynamic.lib and object dynamic.exp
    

    Notice that function foo is defined (differently) in static.lib and dynamic.dll. bar is defined only in static.lib. gum is defined only in dynamic.dll

    Here is a program source that calls foo, bar and gum:

    main.c

    extern void foo();
    extern void bar();
    extern void gum();
    
    int main()
    {
        foo();
        bar();
        gum();
        return 0;
    }
    

    which we compile:

    >cl -c main.c
    Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    main.c
    

    Then we link a program prog like this:

    >link -out:prog.exe main.obj static.lib dynamic.lib
    Microsoft (R) Incremental Linker Version 14.11.25547.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    

    with static.lib first. The program outputs:

    >prog.exe
    foo_static
    bar_static
    gum_dynamic
    

    So foo was resolved from static.lib and the definition from dynamic.dll was ignored.

    Now lets relink with the order of the libraries reversed, and run prog again:

    >link -out:prog.exe main.obj dynamic.lib static.lib
    Microsoft (R) Incremental Linker Version 14.11.25547.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
    >prog.exe
    foo_dynamic
    bar_static
    gum_dynamic
    

    This time, foo was resolved from dynamic.dll and the definition from static.lib was ignored.