5

There are several excellent discussions on SO already covering how to produce an executable shared library on Linux:

In C/C++, this seems relatively straightforward; essentially there are two parts:

  1. Add an .interp section to the ELF (as ld doesn't include one for shared libraries) by including something along these lines in the library source:
    const char interp_section[] __attribute__((section(".interp"))) = "/path/to/dynamic/linker";
  2. Set an appropriate entry point when linking, using -Wl,-e,entry_point

Does anyone know how to achieve this with a library written in Fortran? Specifically, how to add a .interp section to a shared library compiled with ifort?

francescalus
  • 30,576
  • 16
  • 61
  • 96
Ingo
  • 141
  • 3

1 Answers1

5

With help of a C compiler to create an additional object file to be linked to the dynamic library, such a Fortran90 executable and dynamic link library can be created:

/* 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

For compilation and linking:

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

Executing the dynamic link library directly ./libtestif.so will call execentry, and running the link test program

LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./linktest

will call libroutine.

The C code is only needed to create the .interp section. The underscore in the ld flag -Wl,-e,execentry_ is added according to the symbol name mangling for Intel ifort (or GNU gfortran) vs. GNU or Intel C compilers.

v-joe
  • 366
  • 1
  • 4
  • 10
  • Unfortunately, this doesn't work for me. Attempting to execute the shared library results in a segfault. I have confirmed with `readelf` that the `INTERP` section is present, but no dice. – Ingo Aug 26 '21 at 05:49
  • The very same example as in the answer segfaults? If so, this could indicate how fragile / compiler or glibc version dependent this solution might be. On my system, I get a segfault unless I explicitly call exit from the Fortran executable entry routine as described above. – v-joe Aug 26 '21 at 08:22
  • @Ingo can you check the entry point symbol table with something like nm -CD libtestif.so | grep " T " is is something other than execentry_ – Cocofalco Aug 27 '21 at 01:44
  • Yes, same code as the example given above. The entry point is there: `00000000000008a0 T execentry_`. This matches up with the entry point listed by `readelf -h`: `Entry point address: 0x8a0` – Ingo Aug 27 '21 at 05:19