Bug 59888 - Darwin linker error "illegal text-relocation" with -shared
Summary: Darwin linker error "illegal text-relocation" with -shared
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2014-01-20 13:48 UTC by Dominique d'Humieres
Modified: 2019-10-30 12:02 UTC (History)
4 users (show)

See Also:
Host: x86_64-apple-darwin1[234]
Target: x86_64-apple-darwin1[234]
Build: x86_64-apple-darwin1[234]
Known to work:
Known to fail:
Last reconfirmed: 2014-10-04 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dominique d'Humieres 2014-01-20 13:48:12 UTC
For the code at http://gcc.gnu.org/ml/fortran/2014-01/msg00080.html and the modified one below

module F03_ISO_C
  use, intrinsic :: iso_c_binding

  contains

  integer(c_int) function compute() bind(c) result(compute)
    use, intrinsic :: iso_c_binding
    implicit none

    compute = 1
    return

  end function compute

integer function F03_ISO_C_init()
!  use F03_ISO_C
  use, intrinsic :: iso_c_binding

  implicit none

  call USE_FUNC_PTR(c_funloc(compute))

  F03_ISO_C_init = 1
  return

end function F03_ISO_C_init

subroutine USE_FUNC_PTR(f1)
  use, intrinsic :: iso_c_binding

  implicit none

  type(c_funptr) :: f1

  print *, f1, "is the address"

end subroutine USE_FUNC_PTR

end module F03_ISO_C

  use F03_ISO_C
  use, intrinsic :: iso_c_binding

  implicit none

  integer :: i

  i = F03_ISO_C_init()

  print *, i
end

the darwin1(2|3) linker emits the warning

ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in anon from /var/folders/8q/sh_swgz96r7f5vnn08f7fxr00000gn/T//ccA26PZ2.o. To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie

while the output for the above test is

           4294970677 is the address
           1

Compiling the tests with -Wl,-no_pie silences the warning as advertised without changing the output.
Comment 1 Dominique d'Humieres 2014-01-20 13:51:29 UTC
CAVEAT: don't try to use

  print *, F03_ISO_C_init()

or you are likely to be hit by pr30617 (no recursive I/O with the same unit).
Comment 2 Dominique d'Humieres 2014-01-20 19:59:46 UTC
When I opened this PR I missed the "-fshared". With it I get the linker error. On IRC Iain Sandoe gives the following workaround:

(1) gfc -S F03_iso.f90
(2) apply the following patch:

--- F03_iso.s	2014-01-20 20:54:05.000000000 +0100
+++ F03_iso_orig.s	2014-01-20 20:53:06.000000000 +0100
@@ -54,7 +54,7 @@ LCFI4:
 LCFI5:
 	ret
 LFE1:
-	.const
+	.const_data
 	.align 3
 LC2:
 	.quad	_compute

(3) gfc -shared F03_iso.s -o F03_iso.dylib
(4) gfc F03_iso_main.f90 F03_iso.dylib with F03_iso_main.f90 being

  use F03_ISO_C
  use, intrinsic :: iso_c_binding

  implicit none

  integer :: F03_ISO_C_init
  integer :: i

  i = F03_ISO_C_init()

  print *, i
end

Then the executable outputs

           4493950477 is the address
           1

and otool -Lv gives

	F03_iso.dylib (compatibility version 0.0.0, current version 0.0.0)
	time stamp 2 Thu Jan  1 01:00:02 1970
	/opt/gcc/gcc4.9w/lib/libgfortran.3.dylib (compatibility version 4.0.0, current version 4.0.0)
	time stamp 2 Thu Jan  1 01:00:02 1970
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
	time stamp 2 Thu Jan  1 01:00:02 1970
	/opt/gcc/gcc4.9w/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
	time stamp 2 Thu Jan  1 01:00:02 1970
	/opt/gcc/gcc4.9w/lib/libquadmath.0.dylib (compatibility version 1.0.0, current version 1.0.0)
	time stamp 2 Thu Jan  1 01:00:02 1970
Comment 3 Dominique d'Humieres 2014-01-20 20:26:44 UTC
Changed the summary to reflect the original post.
Comment 4 Iain Sandoe 2014-01-20 20:28:06 UTC
So, essentially, the complaint from the darwin linker is that it does not want to see a relocation in the .const section (which is part of the text segment).

It might be argued that this is right/wrong - but it is at least reasonable - the relevant segment should be marked read-only .. but typical darwin relocs can be re-written lazily (as and when the symbol is required).

the hack, proof-of-principle, solution above was to move the reference to the .const_data section.

Whether this is a back-end fault or perhaps a constraint of darwin not present for binutils-ld I cannot tell immediately and would welcome input from the Fortran maintainers as to the decoration intended for the indirect reference produced for c_funloc (defined_function).
Comment 5 Francois-Xavier Coudert 2014-10-03 12:44:18 UTC
Reduced testcase, still failing with -shared on darwin14:

module foo
contains

  subroutine bar
    use, intrinsic :: iso_c_binding
    call gee(c_funloc(gee))
  end subroutine

  subroutine gee(f)
    use, intrinsic :: iso_c_binding
    type(c_funptr) :: f
  end subroutine 

end module foo
Comment 6 Francois-Xavier Coudert 2014-10-04 13:08:57 UTC
(In reply to Iain Sandoe from comment #4)
> Whether this is a back-end fault or perhaps a constraint of darwin not
> present for binutils-ld I cannot tell immediately and would welcome input
> from the Fortran maintainers as to the decoration intended for the indirect
> reference produced for c_funloc (defined_function).

Iain, I am willing to help there but do not understand exactly what you are asking for. Below is a short explanation of what the Fortran front-end is trying to do.

Let's take this code, which compiles fine on darwin:

module foo
contains
  subroutine bar
    use, intrinsic :: iso_c_binding
    call gee(c_funloc(gee))
  end subroutine
  subroutine gee(f)
    use, intrinsic :: iso_c_binding
    type(c_funptr), value :: f
  end subroutine 
end module foo

Here GEE takes as single argument a function pointer, and has no return type. The code in BAR is equivalent to calling gee, with its own address as argument.


Now, the second case passes the GEE argument by reference:

module foo
contains
  subroutine bar
    use, intrinsic :: iso_c_binding
    call gee(c_funloc(gee))
  end subroutine
  subroutine gee(f)
    use, intrinsic :: iso_c_binding
    type(c_funptr) :: f
  end subroutine 
end module foo

This generates the linker error:

ld: illegal text-relocation to '___foo_MOD_gee' in a.o from 'anon' in a.o for architecture x86_64

If you look at the tree dump (-fdump-tree-original), you can see that instead of being just:

bar () { gee(gee); }

in the previous case, it now uses a temporary variable to pass by reference:

bar ()
{
  static void (*<T618>) (void (*<T68>) (void) & restrict) C.2324 = gee;
  gee (&C.2324);
}



Let me know what else I can do to help solve this.
Comment 7 Iain Sandoe 2014-10-04 13:34:32 UTC
Let's work on the principle that the linker is DTRT (it seems reasonable, at least).

---

So, I started to try and replicate what the failing case was doing with a "c" equivalent.

My investigations are not complete (and the usual limited time problem applies) - but so far, it seems - in the c case - that the static variable gets placed in .data (which is fine, from ld64's pov).

As of now, I suspect that the placement into the .const section *might* be fallout from the "restrict" markup.

.. hmm, it's quite hard to point to a useful avenue of exploration (other that confirming that the reference is being lowered as expected, and that the restrict markup is correctly applied).

.. when i have a few more cycles, I'll try and improve my c case to match the fortran more closely.
Comment 8 Francois-Xavier Coudert 2014-10-04 20:28:31 UTC
(In reply to Iain Sandoe from comment #7)
> As of now, I suspect that the placement into the .const section *might* be
> fallout from the "restrict" markup.

To confirm whether it was linked to restrict, I patched the compiler to simply not add the restrict qualifier for f (and later checked that it worked by looking at the tree dumps):

Index: trans-types.c
===================================================================
--- trans-types.c	(revision 215645)
+++ trans-types.c	(working copy)
@@ -2206,7 +2206,7 @@ gfc_sym_type (gfc_symbol * sym)
       else
 	{
 	  type = build_reference_type (type);
-	  if (restricted)
+	  if (0 && restricted)
 	    type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
 	}
     }

However, removing the restrict qualifier doesn't remove the linker error at all. So, I think restrict might be a red herring.
Comment 9 Iain Sandoe 2014-10-16 19:40:15 UTC
do we have a revision # that triggered this behaviour?
(or has it "always" been there?)
Comment 10 Dominique d'Humieres 2014-10-16 20:02:50 UTC
> do we have a revision # that triggered this behaviour?
> (or has it "always" been there?)

Up to r189986 (2012-07-30) compiling the second code in comment 6 gives the error

pr59888_3.f90:5.22:

    call gee(c_funloc(gee))
                      1
Error: Parameter 'gee' to 'c_funloc' at (1) must be BIND(C)

After r190090 (2012-08-02) compiling the same code gives

ld: illegal text-relocation to '___foo_MOD_gee' in /var/folders/8q/sh_swgz96r7f5vnn08f7fxr00000gn/T//ccutec2S.o from 'anon' in /var/folders/8q/sh_swgz96r7f5vnn08f7fxr00000gn/T//ccutec2S.o for architecture x86_64
collect2: error: ld returned 1 exit status

Probably

2012-07-31  Tobias Burnus  <burnus@net-b.de>

        * interface.c (gfc_procedure_use): Return gfc_try instead of void.
        * gfortran.h (gfc_procedure_use): Update prototype.
        * resolve.c (gfc_iso_c_func_interface): Allow noninteroperable
        procedures for c_funloc for TS29113.
        * (gfc_iso_c_sub_interface): Ditto for c_f_procpointer. Add
        diagnostic for c_ptr vs. c_funptr for c_f_(proc)pointer.
Comment 11 Dominique d'Humieres 2014-10-16 20:10:59 UTC
The change occurred at r190003 and an error

Error: TS 29113: Noninteroperable argument 'gee' to 'c_funloc' at (1)

is emitted if one uses -std=f2008.
Comment 12 Francois-Xavier Coudert 2014-10-16 21:48:00 UTC
(In reply to Dominique d'Humieres from comment #11)
> The change occurred at r190003 and an error
> Error: TS 29113: Noninteroperable argument 'gee' to 'c_funloc' at (1)
> is emitted if one uses -std=f2008.

I realize that in simplifying the testcase, I made it non-standard conforming. Try the same revisions with the amended program below, I fear the error message might be a red herring:

module foo
contains
  subroutine bar
    use, intrinsic :: iso_c_binding
    call gee(c_funloc(gee))
  end subroutine
  subroutine gee(f) bind(c)
    use, intrinsic :: iso_c_binding
    type(c_funptr) :: f
  end subroutine 
end module foo
Comment 13 Francois-Xavier Coudert 2014-11-01 09:44:06 UTC
Might this be related with PR63622 (and thus PR63580)?
Comment 14 Eric Gallager 2018-02-19 04:26:02 UTC
(In reply to Francois-Xavier Coudert from comment #13)
> Might this be related with PR63622 (and thus PR63580)?

These have both been closed.
Comment 15 Zaak 2019-04-24 14:43:46 UTC
This is preventing gtk-fortran from compiling on macOS with GCC 8.3, AFAICT.

cd /tmp/gtk-fortran-20190424-36870-ggjnvc/gtk-fortran-19.04.gtk3.24.8/build/src && /usr/local/Cellar/cmake/3.14.3/bin/cmake -E cmake_link_script CMakeFiles/gtk-fortran_shared.dir/link.txt --verbose=1
/usr/local/bin/gfortran -pthread -O2 -fPIC -dynamiclib -Wl,-headerpad_max_install_names -compatibility_version 0.1.0 -current_version 0.1.0 -o libgtk-3-fortran.0.1.dylib -install_name @rpath/libgtk-3-fortran.0.1.dylib CMakeFiles/gtk-fortran_object.dir/atk-auto.f90.o CMakeFiles/gtk-fortran_object.dir/cairo-auto.f90.o CMakeFiles/gtk-fortran_object.dir/gdk-auto.f90.o CMakeFiles/gtk-fortran_object.dir/gdk-pixbuf-auto.f90.o CMakeFiles/gtk-fortran_object.dir/glib-auto.f90.o CMakeFiles/gtk-fortran_object.dir/gtk.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-container.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-button.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-entry.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-tree.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-menu.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-combobox.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-spin-slider.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-chooser.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-dialog.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-progress.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-accelerator.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-infobar.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-assistant.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-hl-misc.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-draw-hl.f90.o CMakeFiles/gtk-fortran_object.dir/gtk-sup.f90.o CMakeFiles/gtk-fortran_object.dir/gdk-pixbuf-hl.f90.o CMakeFiles/gtk-fortran_object.dir/pango-auto.f90.o CMakeFiles/gtk-fortran_object.dir/gdkevents-auto3.f90.o CMakeFiles/gtk-fortran_object.dir/unixonly-auto.f90.o  -L/usr/local/Cellar/plplot/5.14.0_1/lib -Wl,-rpath,/usr/local/Cellar/plplot/5.14.0_1/lib /usr/local/lib/libatk-1.0.dylib /usr/local/lib/libcairo.dylib /usr/local/lib/libgdk-3.0.dylib /usr/local/lib/libgdk_pixbuf-2.0.dylib /usr/local/lib/libglib-2.0.dylib /usr/local/lib/libgio-2.0.dylib /usr/local/lib/libgobject-2.0.dylib /usr/local/lib/libgtk-3.0.dylib /usr/local/lib/libpango-1.0.dylib
ld: illegal text-relocation to '_hl_gtk_listn_edit_cb' in CMakeFiles/gtk-fortran_object.dir/gtk-hl-tree.f90.o from 'lC72' in CMakeFiles/gtk-fortran_object.dir/gtk-hl-tree.f90.o for architecture x86_64
collect2: error: ld returned 1 exit status
make[2]: *** [src/libgtk-3-fortran.0.1.dylib] Error 1
make[1]: *** [src/CMakeFiles/gtk-fortran_shared.dir/all] Error 2
make: *** [all] Error 2
Comment 16 Iain Sandoe 2019-10-05 08:06:16 UTC
Author: iains
Date: Sat Oct  5 08:05:44 2019
New Revision: 276623

URL: https://gcc.gnu.org/viewcvs?rev=276623&root=gcc&view=rev
Log:
[Darwin] Amend section for constants with reloactions.

Darwin's linker doesn't like text section relocations (they require special
enabling).  At least, the Fortran FE seems to generate cases where the
initialiser for a pointer constant can need a relocation.  We can handle
this by special-casing SECCAT_RODATA when the relocation is present by
placing the constant in the .const_data section.

gcc/ChangeLog:

2019-10-05  Iain Sandoe  <iain@sandoe.co.uk>

	PR target/59888
	* config/darwin.c (darwin_rodata_section): Add relocation flag,
	choose const_data section for constants with relocations.
	(machopic_select_section): Pass relocation flag to
	darwin_rodata_section ().


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/darwin.c
Comment 17 Iain Sandoe 2019-10-05 23:13:46 UTC
by the way, I haven't been able to find a C reproducer for this issue - if you feel we should have a testcase for it perhaps a link test for the fortran example would work?
Comment 18 Zaak 2019-10-08 21:25:06 UTC
(In reply to Iain Sandoe from comment #17)
> by the way, I haven't been able to find a C reproducer for this issue - if
> you feel we should have a testcase for it perhaps a link test for the
> fortran example would work?

It would be great to have a test to prevent future regressions here. I have no experience contributing to GCC or using dejagnu but if people are having trouble cooking up a C source to produce an object/library to link the Fortran against, I can try to find something to trigger this.

As I mentioned previously this blocks gtk-fortran from linking on Darwin, however both GTK and gtk-fortran are not adequately small reproducers.
Comment 19 Iain Sandoe 2019-10-16 19:35:46 UTC
(In reply to Zaak from comment #18)
> (In reply to Iain Sandoe from comment #17)
> > by the way, I haven't been able to find a C reproducer for this issue - if
> > you feel we should have a testcase for it perhaps a link test for the
> > fortran example would work?

The Fortran FE folks might also want to convince themselves that the behaviour FX describes in comment #8 is correct.
 
> It would be great to have a test to prevent future regressions here. I have
> no experience contributing to GCC or using dejagnu but if people are having
> trouble cooking up a C source to produce an object/library to link the
> Fortran against, I can try to find something to trigger this.

That's not the problem;
When C generates initialisers for function pointers, these end up in the correct section already, the problem is triggered by something that the  Fortran FE does differently.

So that means it's going to be hard to make a test that lives outside the Fortran testsuite.

A testcase does not have to execute to be useful (a link test using the code at comment #12 would be OK).  However someone has to package the test and decide where it should live in the Fortran testsuite :-)

> As I mentioned previously this blocks gtk-fortran from linking on Darwin,
> however both GTK and gtk-fortran are not adequately small reproducers.

I will back port this in due course.
Comment 20 Iain Sandoe 2019-10-18 08:43:13 UTC
Author: iains
Date: Fri Oct 18 08:42:41 2019
New Revision: 277145

URL: https://gcc.gnu.org/viewcvs?rev=277145&root=gcc&view=rev
Log:
[Darwin] Amend section for constants with relocations.

Darwin's linker doesn't like text section relocations (they require special
enabling).  The Fortran FE, at least, seems to generate cases where the
initialiser for a pointer constant can need a relocation.  We can handle
this by special-casing SECCAT_RODATA when the relocation is present by
placing the constant in the .const_data section.

gcc/

2019-10-18  Iain Sandoe  <iain@sandoe.co.uk>

	Backport from mainline
	2019-10-05  Iain Sandoe  <iain@sandoe.co.uk>

	PR target/59888
	* config/darwin.c (darwin_rodata_section): Add relocation flag,
	choose const_data section for constants with relocations.
	(machopic_select_section): Pass relocation flag to
	darwin_rodata_section ().


Modified:
    branches/gcc-9-branch/gcc/ChangeLog
    branches/gcc-9-branch/gcc/config/darwin.c
Comment 21 Iain Sandoe 2019-10-28 19:40:39 UTC
Author: iains
Date: Mon Oct 28 19:40:03 2019
New Revision: 277540

URL: https://gcc.gnu.org/viewcvs?rev=277540&root=gcc&view=rev
Log:
[Darwin] Amend section for constants with relocations.

Darwin's linker doesn't like text section relocations (they require special
enabling). The Fortran FE, at least, seems to generate cases where the
initialiser for a pointer constant can need a relocation. We can handle
this by special-casing SECCAT_RODATA when the relocation is present by
placing the constant in the .const_data section.

2019-10-28  Iain Sandoe  <iain@sandoe.co.uk>

	Backport from mainline
	2019-10-05  Iain Sandoe  <iain@sandoe.co.uk>

	PR target/59888
	* config/darwin.c (darwin_rodata_section): Add relocation flag,
	choose const_data section for constants with relocations.
	(machopic_select_section): Pass relocation flag to
	darwin_rodata_section ().


Modified:
    branches/gcc-8-branch/gcc/ChangeLog
    branches/gcc-8-branch/gcc/config/darwin.c
Comment 22 Iain Sandoe 2019-10-29 20:05:37 UTC
Author: iains
Date: Tue Oct 29 20:05:05 2019
New Revision: 277584

URL: https://gcc.gnu.org/viewcvs?rev=277584&root=gcc&view=rev
Log:
[Darwin] Amend section for constants with relocations.

Darwin's linker doesn't like text section relocations (they require special
enabling). The Fortran FE, at least, seems to generate cases where the
initialiser for a pointer constant can need a relocation. We can handle
this by special-casing SECCAT_RODATA when the relocation is present by
placing the constant in the .const_data section.

2019-10-29  Iain Sandoe  <iain@sandoe.co.uk>

	Backport from mainline
	2019-10-05  Iain Sandoe  <iain@sandoe.co.uk>

	PR target/59888
	* config/darwin.c (darwin_rodata_section): Add relocation flag,
	choose const_data section for constants with relocations.
	(machopic_select_section): Pass relocation flag to
	darwin_rodata_section ().


Modified:
    branches/gcc-7-branch/gcc/ChangeLog
    branches/gcc-7-branch/gcc/config/darwin.c
Comment 23 Iain Sandoe 2019-10-30 12:02:12 UTC
fixed on open branches