使用ifort构建可执行共享库

5

已经有一些关于如何在Linux上生成可执行共享库的优秀讨论了:

在C/C++中,这似乎相对简单;基本上有两个部分:

  1. 通过在库源代码中包含以下内容向ELF添加.interp部分(因为ld不会为共享库包括此部分):
    const char interp_section[] __attribute__((section(".interp"))) = "/path/to/dynamic/linker";
  2. 使用-Wl,-e,entry_point设置适当的入口点。

有人知道如何在Fortran中实现这一点吗? 具体来说,如何向使用ifort编译的共享库添加.interp部分?

1个回答

5

通过使用C编译器创建一个额外的目标文件来链接到动态库,就可以创建类似Fortran90可执行文件和动态链接库这样的文件:

/* stub.c: compile e.g. with gcc -c stub.c
const char dl_loader[] __attribute__((section(".interp"))) =
    "/lib64/ld-linux-x86-64.so.2";
    /* adjust string if path or architecture is different */

! testif.f90: compile e.g. with ifort -c -fPIC testif.f90

subroutine execentry
    write(*,*) 'Written from executable.'
    ! without call to exit seems to lead to segmentation fault
    call exit(0)
end subroutine

subroutine libroutine
    write(*,*) 'Written by libroutine.'
end subroutine

! linktest.f90: compile e.g. with ifort -c linktest.f90
! main Fortran program for testing

program linktest

call libroutine

end

编译和链接:

gcc -c stub.c
ifort -c -fPIC testif.f90
ifort -c linktest.f90
ifort -shared -o libtestif.so testif.o stub.o -Wl,-e,execentry_
ifort -o linktest linktest.o -L. -ltestif

直接执行动态链接库 ./libtestif.so 将调用 execentry 函数,而运行链接测试程序

LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./linktest

将调用libroutine

仅需要C代码创建.interp节。在ld标志-Wl,-e,execentry_中添加下划线是根据符号名称混淆的规则添加的,适用于Intel ifort(或GNU gfortran)与GNU或Intel C编译器。


很遗憾,这对我不起作用。尝试执行共享库会导致段错误。我已经使用readelf确认了INTERP部分的存在,但是没有成功。 - Ingo
同答案中的示例会出现段错误吗?如果是这样,这可能表明这种解决方案有多么脆弱/依赖于编译器或glibc版本。在我的系统上,除非我从上面描述的Fortran可执行入口例程显式调用exit,否则我会得到一个段错误。 - v-joe
@Ingo,你能否检查一下入口符号表,使用类似于nm -CD libtestif.so | grep " T "的命令,看看是否有其他名称而不是execentry_? - Cocofalco
是的,与上面给出的示例代码相同。入口点在这里:00000000000008a0 T execentry_。这与readelf -h列出的入口点相匹配:入口点地址:0x8a0 - Ingo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接