https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63793

            Bug ID: 63793
           Summary: -mcmodel=medium in gfortran on x86_64 emits references
                    that are RIP relative (instead of using the GOT)
           Product: gcc
           Version: 4.9.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: howarth at bromo dot med.uc.edu

The src_flexwrf_v3.1 package from
http://flexpart.eu/downloads/src_flexwrf_v3.1.tar.gz fails to link on x86_64
darwin when compiled with the required -mcmodel=medium option due to a code
generation bug that the darwin linker fails on. The offending file is compiled
with...

gfortran -c -I/sw/include -fno-common -mcmodel=medium -fconvert=little-endian
-finit-local-zero -fno-range-check convmix_kfeta.f90

and the linkage later fails as...

gfortran *.o -o flexwrf31_gnu_serial -L/sw/lib -fno-common -mcmodel=medium
-fconvert=little-endian -finit-local-zero -fno-range-check -L/sw/lib -lnetcdff 
final section layout:
    __TEXT/__text addr=0x1000017F5, size=0x00126A11, fileOffset=0x000017F5,
type=1
    __TEXT/__stubs addr=0x100128206, size=0x0000023A, fileOffset=0x00128206,
type=28
    __TEXT/__stub_helper addr=0x100128440, size=0x000003C6,
fileOffset=0x00128440, type=32
    __TEXT/__cstring addr=0x100128808, size=0x00000B97, fileOffset=0x00128808,
type=13
    __TEXT/__const addr=0x1001293A0, size=0x0000A6BC, fileOffset=0x001293A0,
type=0
    __TEXT/__eh_frame addr=0x100133A60, size=0x00004598, fileOffset=0x00133A60,
type=19
    __DATA/__got addr=0x100138000, size=0x000002B8, fileOffset=0x00138000,
type=29
    __DATA/__nl_symbol_ptr addr=0x1001382B8, size=0x00000010,
fileOffset=0x001382B8, type=29
    __DATA/__la_symbol_ptr addr=0x1001382C8, size=0x000002F8,
fileOffset=0x001382C8, type=27
    __DATA/__data addr=0x1001385C0, size=0x000008F0, fileOffset=0x001385C0,
type=0
    __DATA/__common addr=0x100138EC0, size=0x000000EC, fileOffset=0x00000000,
type=25
    __DATA/__bss5 addr=0x100138FC0, size=0x00000070, fileOffset=0x00000000,
type=25
    __DATA/__pu_bss5 addr=0x100139040, size=0x000017F0, fileOffset=0x00000000,
type=25
    __DATA/__bss6 addr=0x10013A840, size=0x00855AF4, fileOffset=0x00000000,
type=25
    __DATA/__pu_bss2 addr=0x100990334, size=0x0000047C, fileOffset=0x00000000,
type=25
    __DATA/__pu_bss6 addr=0x1009907C0, size=0x01EBCAA8, fileOffset=0x00000000,
type=25
    __DATA/__pu_bss3 addr=0x10284D268, size=0x00000010, fileOffset=0x00000000,
type=25
    __DATA/__pu_bss4 addr=0x10284D280, size=0x0000001C, fileOffset=0x00000000,
type=25
    __DATA/__bss2 addr=0x10284D29C, size=0x00000020, fileOffset=0x00000000,
type=25
    __DATA/__huge addr=0x10284D2C0, size=0x129E8DD40, fileOffset=0x00000000,
type=25
ld: 32-bit RIP relative reference out of range (4246534707 max is +/-4GB): from
_convmix_kfeta_ (0x100058E3C) to _sumpartgrid.2471 (0x1FD229580) in
'_convmix_kfeta_' from convmix_kfeta.o for architecture x86_64
collect2: error: ld returned 1 exit status

The darwin linker developer has provided the following analysis of this bug...

-----------------------------------------------------------------------------------

This is a little known aspect of x86_64 mach-o that allows the use of the small
code model everywhere (that is not need a large code model).  When the compiler
references “large” ( >= 1MB) zero-fill data, it should do it through the GOT
(instead of direct RIP relative reference).  

When the linker lays out the output, if it is bigger than 2GB, it moves all
large zero-fill symbols to a new __DATA,__huge section which the linker puts
last.  As long as all the uses of moved large data is through the GOT, this
just works and you can have very large mach-o binaries. 

In this case the file from convmix_kfeta.o defines _sumpartgrid.2471  (which is
a 4MB zero-fill symbol) but that same file  has a reference to
_sumpartgrid.2471 from the function _convmix_kfeta_ that is RIP relative
(instead of using the GOT).

Reply via email to