【问题标题】: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
    

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

    这是一个调用foobargum的程序源:

    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
    相关资源
    最近更新 更多