MINGW-packages: binutils 2.35 broken [relocation truncated to fit]

When compiling gnustep base (directly from git source repository, something I am doing since years) I recently fail after a big msys upgrade.

I suppose binutils, given the error:

 Linking library libgnustep-base ...
obj/libgnustep-base.obj/NSObject.m.o:C:\msys64\home\multix\code\libs-base\Source/NSObject.m:605:(.text+0xa3): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `object_getRetainCount_np'
obj/libgnustep-base.obj/NSObject.m.o:C:\msys64\home\multix\code\libs-base\Source/NSObject.m:574:(.text+0xd12): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `objc_release_fast_np'
obj/libgnustep-base.obj/NSObject.m.o:C:\msys64\home\multix\code\libs-base\Source/NSObject.m:552:(.text+0xd33): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `objc_release_fast_no_destroy_np'
obj/libgnustep-base.obj/NSObject.m.o: in function `release_fast_no_destroy':
C:\msys64\home\multix\code\libs-base\Source/NSObject.m:554:(.text+0xd3d): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `objc_release_fast_no_destroy_np'
obj/libgnustep-base.obj/NSObject.m.o:C:\msys64\home\multix\code\libs-base\Source/NSObject.m:702:(.text+0x2c83): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `objc_retain_fast_np'
obj/libgnustep-base.obj/NSObject.m.o:C:\msys64\home\multix\code\libs-base\Source/NSObject.m:552:(.text+0x2d93): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `objc_release_fast_no_destroy_np'
obj/libgnustep-base.obj/NSObject.m.o:C:\msys64\home\multix\code\libs-base\Source/NSObject.m:605:(.text+0x2dc3): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `object_getRetainCount_np'
obj/libgnustep-base.obj/NSObject.m.o:C:\msys64\home\multix\code\libs-base\Source/NSObject.m:605:(.text+0x2dfb): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `object_getRetainCount_np'
obj/libgnustep-base.obj/NSObject.m.o: in function `getRetainCount':
C:\msys64\home\multix\code\libs-base\Source/NSObject.m:607:(.text+0x2e05): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `object_getRetainCount_np'
obj/libgnustep-base.obj/NSObject.m.o:C:\msys64\home\multix\code\libs-base\Source/NSObject.m:702:(.text+0x2e33): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `objc_retain_fast_np'
obj/libgnustep-base.obj/NSObject.m.o: in function `getRetainCount':
C:\msys64\home\multix\code\libs-base\Source/NSObject.m:607:(.text+0xad): additional relocation overflows omitted from the output
collect2.exe: error: ld returned 1 exit status

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 21 (10 by maintainers)

Commits related to this issue

Most upvoted comments

I can post it in the bug report next week with more details.

That kind of explains how the symbols could be undefined. But again, I was under the impression that the Windows loader doesn’t support weak symbols. More magic I guess.

AFAIK MSVC linker does not support weak symbols and it doesn’t even support any of __attribute__. Mingw-w64 GCC+LD can use weak symbols but they are buggy. AFAICT they work correctly when used within single object but when the same weak symbols are used by multiple objects it often fails with undefined references and multiple definition errors. Clang up to version 10 did not support (replaced them with standard symbols) weak symbols at all for mingw-64. Clang 11 supports them though but it requires more testing.

@mati865 thanks for looking at this.

So what really happens is the linker will use it’s heuristic to guess which symbols should be exported. New binutils package enables high entropy ASLR by default which breaks incorrect assumptions like that.

That’s an intriguing statement.

I just noticed this:

/* platforms which do not support weak */
#if (__GNUC__ == 3) && defined (__WIN32)
#define WEAK_ATTRIBUTE
#undef SUPPORT_WEAK
#else
/* all platforms which support weak */
#define WEAK_ATTRIBUTE __attribute__((weak))
#define SUPPORT_WEAK 1
#endif

and

/*
 * These symbols are provided by newer versions of the GNUstep Objective-C
 * runtime.  When linked against an older version, we will use our internal
 * versions.
 */
WEAK_ATTRIBUTE
BOOL objc_release_fast_no_destroy_np(id anObject);

WEAK_ATTRIBUTE
void objc_release_fast_np(id anObject);

WEAK_ATTRIBUTE
size_t object_getRetainCount_np(id anObject);

WEAK_ATTRIBUTE
id objc_retain_fast_np(id anObject);

That kind of explains how the symbols could be undefined. But again, I was under the impression that the Windows loader doesn’t support weak symbols. More magic I guess.

@rmottola I’ve looked at the code and it’s probably bug with gnustep base.

With newer binutils package you can try to workaround it by passing -Wl,--disable-dynamicbase,--default-image-base-low to the linker (LDFLAGS="-Wl,--default-image-base-low for most of the build systems) to disable ASLR.


About the bug: Look at this line https://github.com/gnustep/libs-base/blob/fc0c0da188eb4ee2800ab9643394aa16660ef6bd/Headers/GNUstepBase/GSVersionMacros.h#L383:

# if defined(__MINGW__)
  /* On Mingw, the compiler will export all symbols automatically, so
   * __declspec(dllexport) is not needed.
   */

No, the compiler won’t export all the symbols. The linker would export all symbols if --export-all-symbols was passed to it but that doesn’t seem to happen anywhere in libs-base code. So what really happens is the linker will use it’s heuristic to guess which symbols should be exported. New binutils package enables high entropy ASLR by default which breaks incorrect assumptions like that.

You should try removing those lines so it looks like this:

#if BUILD_libgnustep_base_DLL
#  define GS_EXPORT  __declspec(dllexport)
#  define GS_DECLARE __declspec(dllexport)
#else
#  define GS_EXPORT  extern __declspec(dllimport)
#  define GS_DECLARE __declspec(dllimport)
#endif