静态存档中的C符号可见性 [英] C symbol visibility in static archives

查看:125
本文介绍了静态存档中的C符号可见性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有文件foo.c bar.c和baz.c,以及封装代码myfn.c,它定义了一个函数myfn(),它使用来自其他文件的代码和数据。



我想创建一个类似于目标文件或存档,myfn.o或libmyfn.a的东西,这样可以使myfn()可用于其他项目,而不会导出{foo,bar, baz} .o。



在Linux / gcc中,正确的方法是做什么?谢谢。






更新:我找到了一种方法。我原本应该强调这是关于静态档案,而不是DSO。无论如何,配方:
$ b $ ol #define PUBLIC __attribute__((visibility(default))) 然后在 myfn.c中将 myfn()标记为 PUBLIC 。不要标记任何东西 PUBLIC

  • 使用编译对象gcc - c foo.c bar.c baz.c myfn.c -fvisibility = hidden ,除了 myfn()以外, / p>

  • 使用 ld 的部分链接开关创建一个便捷存档: ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a


  • 本地化所有不是 PUBLIC 就像这样: objcopy --localize-hidden libmyfn.a

  • $ b $现在 nm 表示 myfn libmyfn中唯一的全局符号.a 并且随后链接到其他程序中工作得很好: gcc -o main main.c -L。 -lmyfn (这里,程序调用 myfn();如果它试图调用 foo()

    如果我使用 ar $ c>代替 ld -r 在步骤3中,那么编译在步骤5中失败:我猜想 ar 没有将 foo 等链接到 myfn ,并且不再能够一旦这些函数被本地化,而 ld



    我欢迎任何回应,证实这是正确的的方式,或描述一种实现相同的方式。 解决方案

    - 或者什么都没有,因为所有模块的全局变量都可以在 libmyfn.a 的外部符号的最终列表中找到。



    gcc 工具链提供了一个扩展,可让您从外部用户中隐藏符号,同时使其可用到您图书馆的其他翻译单元:

    foo.h:

      void foo(); 

    foo.c:

      void foo()__attribute__((visibility(hidden))); 

    myfn.h:

      void myfn(); 

    myfn.c:

      #include< stdio.h> 
    #includefoo.h

    void myfn(){
    printf(calling foo ... \\\
    );
    foo();
    printf(再次调用foo ... \\\
    );
    foo();
    }

    为便于携带,您可能会从为 __ attribute__((visibility(hidden))),并将它放在一个以 gcc 为条件的条件编译块中。



    另外,Linux提供了一个实用程序称为 strip ,它可以让你从编译目标文件中删除一些符号。选项 -N -K 可让您识别要保留或移除的单个符号。


    I have files foo.c bar.c and baz.c, plus wrapper code myfn.c defining a function myfn() that uses code and data from those other files.

    I would like to create something like an object file or archive, myfn.o or libmyfn.a, so that myfn() can be made available to other projects without also exporting a load of symbols from {foo,bar,baz}.o as well.

    What's the right way to do that in Linux/gcc? Thanks.


    Update: I've found one way of doing it. I should've emphasised originally that this was about static archives, not DSOs. Anyway, the recipe:

    1. #define PUBLIC __attribute__ ((visibility("default"))) then mark myfn() as PUBLIC in myfn.c. Don't mark anything else PUBLIC.

    2. Compile objects with gcc -c foo.c bar.c baz.c myfn.c -fvisibility=hidden, which marks everything as hidden except for myfn().

    3. Create a convenience archive using ld's partial-linking switch: ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a

    4. Localise everything that wasn't PUBLIC like so: objcopy --localize-hidden libmyfn.a

    5. Now nm says myfn is the only global symbol in libmyfn.a and subsequent linking into other programs works just fine: gcc -o main main.c -L. -lmyfn (here, the program calls myfn(); if it tried to call foo() then compilation would fail).

    If I use ar instead of ld -r in step 3 then compilation fails in step 5: I guess ar hasn't linked foo etc to myfn, and no longer can once those functions are localised, whereas ld -r resolves the link before it gets localised-away.

    I'd welcome any response that confirms this is the "right" way, or describes a slicker way of achieving the same.

    解决方案

    Unfortunately, C linkage for globals is all-or-nothing, in the sense that the globals of all modules would be available in libmyfn.a's final list of external symbols.

    gcc tool chain offers an extension that lets you hide symbols from outside users, while making them available to other translation units in your library:

    foo.h:

    void foo();
    

    foo.c:

    void foo() __attribute__ ((visibility ("hidden")));
    

    myfn.h:

    void myfn();
    

    myfn.c:

    #include <stdio.h>
    #include "foo.h"
    
    void myfn() {
        printf("calling foo...\n");
        foo();
        printf("calling foo again...\n");
        foo();
    }
    

    For portability, you would probably benefit from making a macro for __attribute__ ((visibility ("hidden"))), and placing it in a conditional compilation block conditioned on gcc.

    In addition, Linux offers a utility called strip, which lets you remove some of the symbols from compiled object files. Options -N and -K let you identify individual symbols that you want to keep or remove.

    这篇关于静态存档中的C符号可见性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆