【问题标题】:Removing symbols from object file on windows从 Windows 上的目标文件中删除符号
【发布时间】:2018-10-11 11:56:20
【问题描述】:

有没有办法在目标文件中删除(或制作本地)符号?我正在寻找类似objcopy --keep-global-symbol on linux 的东西。

或者也许有办法告诉链接器应该隐藏哪些符号?我找到了这个页面:https://msdn.microsoft.com/en-us/library/28d6s79h.aspx,它描述了 .Def 文件,我从阅读中得到的印象是,我不仅可以将这些文件用于 dll,还可以用于静态库。这是真的吗?

我需要这个,因为我链接了两个库 A 和 B,它们导出相同的符号。 A是动态链接的,B是静态链接的。如果 A 和 B 都导出了一个符号,我希望我的应用程序使用 A 中的符号,另外我想使用 B 中的一些符号(仅在 B 中)。

【问题讨论】:

    标签: windows visual-c++ linker object-files


    【解决方案1】:

    如果您安装了 Mingw GCC 端口之一,例如mingw-w64, 那么您还将获得用于 Windows PE 二进制文件的 binutils 的端口,并且您将能够使用 熟悉的objcopy --keep-global-symbol。

    在您选择的安装的bin 目录中找到它,例如C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev0\mingw64\bin

    但是...

    你很可能在这里有一个XY problem, 因为链接器将解析输入序列中第一个库中的符号 定义它并忽略以后库中的定义;所以你可以 仅通过在静态之前链接它来优先考虑来自 DLL 的定义 图书馆。插图:

    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");
    }
    

    编译*_static.c源文件并将目标文件归档到静态库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.
    

    编译*_dynamic.c源文件并链接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
    

    请注意,函数 foo 在 static.lib 和 dynamic.dll 中定义(不同)。 bar 仅在 static.lib 中定义。 gum 仅在 dynamic.dll 中定义

    这是一个调用foo、bar和gum的程序源:

    ma​​in.c

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

    我们编译的:

    >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
    

    然后我们像这样链接一个程序prog:

    >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.
    

    首先是static.lib。程序输出:

    >prog.exe
    foo_static
    bar_static
    gum_dynamic
    

    所以foo 是从static.lib 解析的,而定义是从 dynamic.dll 被忽略了。

    现在让我们重新链接库的顺序,然后再次运行prog:

    >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
    

    这一次,foo 是从 dynamic.dll 解析的,而定义是从 static.lib 被忽略了。

    【讨论】:

    • 谢谢,我会尝试,但理想情况下我宁愿不安装任何额外的程序。您是否知道我刚刚在编辑中添加的问题的答案(关于 .Def 文件)?
    • @Igor 不,.def 文件只能由链接器在程序或 DLL 的链接中使用。不是静态库,因为与程序或 DLL 不同,静态库不是由链接器 (link) 生成的,它只是由存档器 (lib) 生成的。见static-libraries。但是我的扩展答案可能会有所帮助。
    • 谢谢你的解释,这确实解决了我的问题。我是否正确理解(从您发布的链接)这种行为取决于链接器?这会在 linux(使用 GNUs ld)上给出相同的结果吗?
    • @Igor 是的,这种行为与 GNU/Linux 工具链相同
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 2018-06-15
    • 2013-09-05
    相关资源
    最近更新 更多