代码之家  ›  专栏  ›  技术社区  ›  masec

调用另一个对象文件中的函数而不在共享库中使用plt?

  •  1
  • masec  · 技术社区  · 8 年前

    我有两个装配代码, code1.s code2.s 我想从这两个构建一个可重定位(使用-fpic开关)共享库。

    我想要 代码2 调用函数,命名为 myfun1 ,其定义见 代码1 .

    当我使用 call myfun1@PLT 在里面 代码2 它找到了这个函数,它的工作方式就像一个魅力,但它使用plt部分来调用这个函数,这个函数在同一个共享库中。我想在不遵守PLT部分的情况下完成这项工作。当我删除 @PLT 我得到了 relocation R_X86_64_PC32 against symbol 误差为 MyFun1 .

    如果不使用plt部分,我该怎么做?有什么办法吗?我认为它应该是可行的,因为共享库应该是可重定位的,但不需要它的每个对象文件,所以为什么在同一个库中调用一个函数应该经过PLT部分。

    以下是我的编译命令:

    抄本:

    gcc -c codeX.s -fPIC -DPIC -o codeX.o
    

    gcc -c codeX.s -o codeX.o
    

    对于名为libcodes.so的共享库:

    gcc -shared -fPIC -DPIC -o libcodes.so code1.o code2.o
    

    正如您可能好奇我为什么这样做,我有许多对象文件,它们每个都想调用 MyFun1 . 在这里,我只是简化了询问技术部分。即使我试着 MyFun1 总共 codeX.s 但我得到的错误是 MyFun1 定义了多次。我不太在乎空间,如果我能 MyFun1 在所有文件中。

    2 回复  |  直到 8 年前
        1
  •  3
  •   Peter Cordes    8 年前

    在一个源文件中,您只能使用两个标签( Building .so with recursive function in it 一) .globl 另一个则不然。但在共享库中的源文件中,这还不够。

    对于同样导出的函数,结合下面的答案仍然有用:一个是隐藏的,另一个不是,这样您就可以在库中有效地调用。


    使用 格洛尔 .hidden 创建可以在当前对象文件外部看到的符号,但 在共享库之外。 因此,它不受符号插入的影响,来自同一共享库中其他文件的调用可以直接调用它,而不是通过PLT或GOT。

    测试和工作示例 :

    ## foo.S
    .globl myfunc
    .hidden myfunc
    myfunc:
       #.globl myfunc_external    # optional, a non-hidden symbol at the same addr
       #myfunc_external:
        ret
    

    ## bar.S
    .globl bar
    bar:
        call myfunc
        ret
    

    建立与 gcc -shared foo.S bar.S -o foo.so objdump -drwC -Mintel foo.so :

    Disassembly of section .text:
    
    000000000000024d <myfunc>:
     24d:   c3                      ret    
    
    000000000000024e <bar>:
     24e:   e8 fa ff ff ff          call   24d <myfunc>     # a direct near call
     253:   c3                      ret    
    

    (我实际上是用 -nostdlib 例如,为了保持反汇编输出的清洁,可以省略其他函数,例如 __do_global_dtors_aux register_tm_clones .init 部分)


    我认为glibc使用了strong或 weak_alias 为此( what does the weak_alias function do and where is it defined ,因此来自共享库的调用可以使用普通名称。 Where are syscalls located in glibc source ,例如 __chdir chdir .

    例如 glibc's printf.c 定义 __printf 并使 printf 坚强的 别名。

    io/chdir.c 定义 第二代 并使 切迪尔 虚弱的 别名。

    其中一个x86-64 memchr asm实现还使用 strong_alias 宏(位于文件底部)。


    相关气体指令如下:

    没有强别名气体指令。这可能相当于 foo = foo_internal 或等效物 .set foo, foo_internal .

    (托多:完整的例子和关于强弱关系的更多细节。我目前还不知道,所以如果我不亲自阅读文档,欢迎编辑。 我知道这些东西存在并解决了这个问题,但我不知道具体如何解决。)

        2
  •  0
  •   masec    8 年前

    好吧,我找不到任何办法,但是当我编辑我的问题时,我不想说 myfun1 在所有对象文件中。

    我遇到的问题是链接器输出了我定义的错误 MyFun1 在很多地方,这都是因为我 globl 指令 MyFun1 当我拆下那根线的时候,它就修好了。

    感谢罗斯·里奇再次催促我尝试。

    推荐文章