【问题标题】:Building an executable shared library with ifort使用 ifort 构建可执行共享库
【发布时间】:2021-10-25 04:48:03
【问题描述】:

关于 SO 的一些精彩讨论已经涵盖了如何在 Linux 上生成可执行共享库:

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

  1. 在 ELF 中添加一个 .interp 部分(因为 ld 不包括用于共享库的部分),方法是在库源中包含以下内容:
    const char interp_section[] __attribute__((section(".interp"))) = "/path/to/dynamic/linker";
  2. 在链接时设置适当的入口点,使用-Wl,-e,entry_point

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

【问题讨论】:

    标签: fortran shared-libraries intel-fortran


    【解决方案1】:

    在 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 部分存在,但没有骰子。
    • 与答案段错误中的示例完全相同?如果是这样,这可能表明该解决方案可能有多脆弱/编译器或 glibc 版本依赖。在我的系统上,除非我如上所述从 Fortran 可执行条目例程中显式调用 exit,否则会出现段错误。
    • @Ingo 你能用类似 nm -CD libtestif.so 的东西检查入口点符号表吗? grep "T" 不是 execentry_
    • 是的,代码与上面给出的示例相同。入口点在那里:00000000000008a0 T execentry_。这与readelf -h 列出的入口点匹配:Entry point address: 0x8a0
    猜你喜欢
    • 1970-01-01
    • 2021-07-17
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    相关资源
    最近更新 更多