From which version of gcc does -mcmodel=large work? - gcc

I have code which produces executables larger than 2GB (it's generated code).
On x64 with gcc 4.3.2 I get errors like:
crtstuff.c:(.text+0x20): relocation truncated to fit:
R_X86_64_32S against `.dtors'
So I understand i need the -mcmodel=large option. However that doesn't do anything or solve the problem on my system.
I am sure I read somewhere, that it was only supported from a particular version of gcc, and the option was ignored on versions before that. I would tell my operations team to install that version of gcc if only I knew what it was. But I just can't find any evidence right now to tell me if that hypothesis is true, and if so in which version the feature was introduced.
For example
(1) Here it is stated that the option doesn't do anything. The book in question claims to cover "GCC 4.x". The book came out 2006.
(2) Here a compiler bug is being reported against the option, therefore I conclude in that version it must do at least something. That seems to be gcc 4.6.1.
So although I can no longer find evidence of exactly in which version the feature was implemented, at least there is evidence that this has changed over time.
I have tried looking through the changelogs for all the various GCC 4.x versions to no avail (and normally they are pretty good so the lack of information there almost implies that I am wrong and nothing has changed between versions.)
Edit: This seems to imply that perhaps it did work, but I need to "recompile crtstuff.c", but I don't really know where I find that file or how I do that.

I believe 4.4 is the version that added support for this feature. I demonstrate below that 4.1 doesn't work while 4.4 does, on something that needs a large data block (rather than code). I'm not sure about 4.2 and 4.3, but both your example and my memory suggest 4.3 didn't have working support for this. My example should let you validate whether a particular installation works or not though, on an otherwise easy to compile bit of code.
As background, I maintain a program that's a fork of the stream benchmark, modified specially to use 64 bit structures for testing larger systems. I was plagued with these "relocation truncated to fit" errors until I started using "-mcmodel=large", and my fork won't compile/run unless that really does work. The oldest version of gcc I've definitely found my program compatible with is the 4.4.5 that ships with Debian Squeeze.
Here's a complete test case showing my fork of stream compiling and using >4GB of RAM with the large model, after failing to do so without the option:
$ gcc --version
gcc (Debian 4.4.5-8) 4.4.5
...
$ git clone https://github.com/gregs1104/stream-scaling.git
$ cd stream-scaling
$ gcc -O3 -DN=200000000 -fopenmp stream.c -o stream
/tmp/cca8rR1I.o: In function `checkSTREAMresults':
stream.c:(.text+0x34): relocation truncated to fit: R_X86_64_32S against `.bss'
...
stream.c:(.text+0x6ab): additional relocation overflows omitted from the output
collect2: ld returned 1 exit status
$ gcc -O3 -DN=200000000 -fopenmp stream.c -o stream -mcmodel=large
$ ./stream
-------------------------------------------------------------
STREAM version $Revision: 5.9 $
-------------------------------------------------------------
This system uses 8 bytes per DOUBLE PRECISION word.
-------------------------------------------------------------
Array size = 200000000, Offset = 0
Total memory required = 4577.6 MB.
...
And here's what happens on a version of gcc that doesn't have the large model, one running RedHat 5 derived software (CentOS 5.8):
$ gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-52)
...
$ gcc -O3 -DN=200000000 -fopenmp stream.c -o stream -mcmodel=large
stream.c:1: sorry, unimplemented: code model ‘large’ not supported yet
So on older versions of gcc, it should throw that error out, not just ignore the option.
crtstuff is a library coming with gcc. The bug report you linked to on the gcc mailing list was from someone trying to build their own gcc for a RedHat 5 system, which as you can see in this last example ships with gcc 4.1. They rebuilt part of gcc with the large model, but it was still linking against the original, 4.1 built crtstuff library. You shouldn't run into that problem if you're using a properly packaged gcc, which is why it wasn't considered a real bug by the gcc developers. I think you just need gcc 4.4 or later.

Related

Section `text` will not fit after upgrading `arm-none-eabi-gcc`

I have an open source micromouse robot project. For easier compilation, I use containers (both Podman and Docker should be fine):
make image
make libopencm3
make
This works just fine and generates a main.elf file about 874 kB in size. But that is as long as I fix the arm-none-eabi-gcc-cs to 7.4.0 in the Dockerfile.
If I remove the specific version or set it to 9.2.0, then I get the following error:
$ make
/usr/lib/gcc/arm-none-eabi/9.2.0/../../../../arm-none-eabi/bin/ld: main.elf section `.text' will not fit in region `rom'
/usr/lib/gcc/arm-none-eabi/9.2.0/../../../../arm-none-eabi/bin/ld: region `rom' overflowed by 5288 bytes
collect2: error: ld returned 1 exit status
make: *** [opencm3/libopencm3.rules.mk:204: main.elf] Error 1
What could have changed between those versions?
If I add this line to my Makefile:
LDFLAGS += -specs=nano.specs
Then it compiles just fine with version 9.2.0 and generates a main.elf file about 885 kB in size. But I wonder if the performance would be the same (or equivalent) as before.
Update
I am expecting some performance differences, of course, just like I was expecting some differences in the binary size. But I was wondering if I could expect a higher than 20% difference in performance (specially if it could be now 20% slower).
The new binary is less than 2% bigger, and I would consider this to be "the same" as before. :-D
I do perfectly understand you want to use the latest and greatest toolchain from your prefered, mainstream Linux distribution, but this is not always going well.
In my humble opinion, you should:
stick to Linaro or ARM gcc toolchains,
in the case of your specific cortex-m related project, stick to a gcc toolchain more specifically targeting the cortex-m, i.e. the so called 'GNU Arm Embedded Toolchain'.
Some remarks:
There are probably excellent reasons why ARM itself is providing two specifics toolchains for the two profiles,
Latest GCC toolchain version available from Linaro is 7.4.1, but if they used to point to it by default on this page, they now pointing to version 7.2.1, which may (or not) ring a bell regarding 7.4.1 - there are no official 9.2 versions available yet.
Latest GCC toolchain available from ARM is 8.3.1 for cortex-m, and 8.3 for cortex-a - there are no official 9.2 versions available yet.
Back to your specific issue now: I was able to compile your project using the following steps:
wget "https://developer.arm.com/-/media/Files/downloads/gnu-rm/8-2019q3/RC1.1/gcc-arm-none-eabi-8-2019-q3-update-linux.tar.bz2?revision=c34d758a-be0c-476e-a2de-af8c6e16a8a2?product=GNU%20Arm%20Embedded%20Toolchain,64-bit,,Linux,8-2019-q3-update" -O gcc-arm-none-eabi-8-2019-q3-update-linux.tar.bz2
mkdir -p /opt/arm
tar jxf gcc-arm-none-eabi-8-2019-q3-update-linux.tar.bz2 -C /opt/arm
export PATH=/opt/arm/gcc-arm-none-eabi-8-2019-q3-update/bin:$PATH
Command which arm-none-eabi-gcc should display /opt/arm/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-gcc.
git clone --recurse-submodules https://github.com/Bulebots/bulebule.git
cd bulebule
scripts/setup_libopencm3.sh
make -s -C src/
Command arm-none-eabi-size ./src/main.elf should display:
text data bss dec hex filename
55152 3336 7100 65588 10034 ./src/main.elf
Please note that there is a Docker file for the latest GCC toolchain from ARM targeting the cortex-m profile here. You may want to use it in your own Docker file and remove those two lines:
arm-none-eabi-gcc-cs-7.4.0 \
arm-none-eabi-newlib-3.1.0-2.fc30 \
I hope this helps.

how does "make" determine which linker to use?

I wanted to upgrade to binutils 2.26 , so i followed the steps here : How to convert default binutils into binutils-2.26? to solve the same "unrecognized relocation" error.
Now my default linker is 2.26
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.26.1
Copyright (C) 2015 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
But "make" still uses the "/usr/bin/x86_64-linux-gnu-ld" (which is 2.24) and still gives the same error.
So how to force "make" to use the default linker ?
It depends upon your Makefile (which you could debug with remake -x). Notice that make has a lot of builtin rules. Use make -p to also print them. Notice the rules mentioning LINK.c or LINK.cc etc, and notice that LD is not much used. Notice also that ld is almost never used directly (most of the time, some other program like gcc or g++ runs it).
And it is also a matter of the PATH variable. So try setting it so that your new ld comes before the old one.
Generally, you link with the gcc or g++ program (so it is GCC which matters, not make; read about Invoking GCC and its -fuse-ld=), and that gcc or g++ will run the linker (you might, but I don't recommend to, change its spec file which governs what actual programs are run by gcc or g++ which are only drivers to other programs such as cc1, as, ld, collect2 etc...). To understand what programs gcc or g++ is running, pass it the -v flag.
But "make" still uses the "/usr/bin/x86_64-linux-gnu-ld" (which is 2.24) and still gives the same error.
On my Debian system /usr/bin/x86_64-linux-gnu-ld (it is generally started by gcc, not directly by make) is a symlink. You might (but I don't recommend that) just change that symlink.
BTW, you are using an ancient Ubuntu 14. You'll better upgrade your entire distribution (e.g. to Ubuntu 18.04.1 LTS at end of 2018), because there is not only ld but many other programs which are really old on your system.
Upgrading your distribution will take less time than upgrading, compiling, installing and configuring each individual tool.

LD needs DWARF version 3 or 2, but mine is version 4

After hours of research (and tries) on how to install id3lib on Qt (windows), but with no success, I decided to use TagLib's library.
I followed this tutorial to build a compatible version of taglib for Qt but still another problem (full log here):
...
C:\MinGW\bin\..\lib\gcc\mingw32\3.4.5\..\..\..\..\mingw32\bin\ld.exe: Dwarf
Error: found dwarf version '4', this reader only handles version 2 and 3
information.
C:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../mingw32/lib/crt2.o:crt1.c:(.text+0x1f1):
undefined reference to `__chkstk_ms'
...
In CMake, I did configure > MinGW Makefiles.
Can anyone tell how to fix it?
Environment:
Windows 7 (64-bit);
CMake 2.8.12.1;
TagLib 1.9.1;
GCC 3.4.5;
Qt 5.1.1.
The problem stems from the fact that you are using terribly outdated GCC, while your Qt binaries are most likely built with bleeding-edge GCC (or the one close to it). For instance, as the error message shows, DWARF is outdated in case of your current GCC and is incompatible with the one used by your current Qt. Furthermore, even if it wouldn't, you'd still hit other problems with binary incompatibilities, since you essentially mix compilers with different major version numbers, which is strongly discouraged. Notice, that your problem has nothing to do with CMake at all. You can see it yourself in the error message, i.e. the error is reported by ld, the linker utility from (your outdated) GCC toolchain. To conclude, your only option is to update GCC, ideally exactly to the one which was used to build your current Qt.

Old version of libc linking with my binary

I have inherited a piece of software which is having some issues. I believe the issues are related to the version of libc that is being statically linked.
I am building this on a Windows XP machine, targeting an x86 QNX Neutrino 6.3.2 machine.
Previously, the software built with GCC 2.95.3 (Well, technically, it's QNX's QCC that wraps and calls GCC)
Someone added a feature and had to port it to build with GCC 3.3.5 because the new feature needed it.
Now, the software is mine. I need to make some additions but have noticed weird behavior. After some digging, I found that there are static links to both libc for 2.95.3 and 3.3.5. According to QNX's web site, :
GCC 2.95.3 (from 6.2.1 or 6.3) and GCC 3.3.5 use different C++ ABIs
and have different name mangling. As a result, you can't link C++
binaries (objects, executables, libraries) built with GCC 2.95.3 with
binaries built with GCC 3.3.5.
This is a breaking ABI change, so I am obviously concerned. I wrote a small test for this
#include <stdio.h>
int main()
{
FILE *stream_ptr = popen("fakename","r"); /// use libc
return 0;
}
and built it with 3.3.5:
QCC -V3.3.5,gcc_ntox86 small.cpp -o small.out
then used strings to see what has been statically linked for this program
strings -a small.out | grep GCC
GCC: (GNU) 3.3.5 (qnx-nto)
GCC: (GNU) 3.3.5 (qnx-nto)
GCC: (GNU) 2.95.3
GCC: (GNU) 3.3.5 (qnx-nto)
As you can see, libc for GCC 2.95.3 has been statically linked.
My first question is: How can I make this link with a 3.3.5 version of libc?
My second question is: Why does it link with 2.95.3 in the first place?
What am I doing wrong/missing? Any suggestions are welcome.
(There's probably 60 other things in the project linking with 2.95.3 objects, and I need to fix them all, so implementing popen() and 59 of his closest friends myself isn't the best of ideas...)
Thanks,
Karl
UPDATE:
So I haven't figured out how to fix this yet, but a little bit of background for QNX 6.3.2 so folks who stumble upon this later don't have to figure this out the hard way:
You can use the verbose option for the linker ld --verbose and have it spit out everything it does. Note that I got the following output when I did that:
attempt to open C:/QNX632/host/win32/x86/usr/lib/gcc-lib/i386-pc-nto-qnx6.3.0/3.3.5//libc.a failed
attempt to open C:/QNX632/target/qnx6/x86/lib/gcc/3.3.5/libc.a failed
attempt to open C:/QNX632/target/qnx6/usr/i386-pc-nto-qnx6.3.0/lib//libc.a failed
attempt to open C:/QNX632/target/qnx6/usr/lib/libc.a failed
attempt to open C:/QNX632/target/qnx6/x86/lib//libc.a succeeded
As one can see, the linker is attempting to open the 3.3.5 version of libc.a, but it's simply not there. I took a look at 3 other coworkers computers, and the 3.3.5 version of libc.a is not there. How this is even working across a breaking ABI change, I'm not sure, but I am suspicious that some of the wonkiness in this project has to do with this discrepancy.
While this answers my original questions,
1) You can't make it link with nonexistant libc.a files,
2) It picks the 2.95.3 version because the 3.3.5 version isn't there,
it brings up new questions:
3) Why doesn't QNX ship a 3.3.5 version of libc.a with this version of Momentics? (or if they do, where do they hide it because I missed it.)
4) Are there any viable workarounds? I was able to build everything but the two most important servers in the project without using libc, but until I get the last two fixed up, I'm still searching for a solution.
Update to the Update:
Working with the QNX folks, they built me an unsupported, untested engineering version of libc.a, libm.a and libsocket.a with GCC 3.3.5, and everything has been good since.
When I compile for QNX 6.3.2, I always use 3.3.5 with the GNU C/C++ libraries. If you don't specify GNU, you will get Dinkum libraries by default. I have had problems in the past with Dinkum thread safety. Try these flags:
qcc -V3.3.5,gcc_ntox86 -Y_gpp
The -Y_gpp directs qcc to use the GNU libraries.
GCC 3.3 is prehistoric, isn't there a newer version for QNX?
There should be some option for the compiler or linker which will tell it to be verbose, which you could use to see all the library paths and libraries being linked to. That might show you how an older lib is being linked to.
In case someone else runs into a similar problem, to the best of my knowledge, here are the answers to the four questions I asked. They are not encouraging.
1) You can't make it link with nonexistent libc.a files. Of course.
2) It picks the 2.95.3 version of libc.a because the 3.3.5 version isn't there.
3) During discussions with the QNX folks, they stated that for QNX Neutrino 6.3.2, the official, tested compiler is only 2.95.3, even though GCC 3.3.5 is included in the shipped version of Momentics, it is not tested nor supported. It just happens to be there.
4) Options:
a) Go to a newer version of QNX which uses a newer version of GCC
b) Get source for libc (and libm as it turns out) and build it with GCC 3.3.5.
This one may pan out. Still waiting on QNX tech support.
c) Get already-built libraries from the QNX folks.
d) Don't use GCC 3.3.5 to build for Neutrino 6.3.2
Sincerely,
Karl

g++ 4.4.x bug?

I have build a g++ v4.4 from source by using the archives provided by gcc.gnu.org.
But the resulting g++ cannot compile some of our projects c++ files. I am receiving a message simply saying: assembler error. It turned out that the assembler chokes on some extremely long symbol names, e.g. symbols names with a length of more then 2k.
Am I missing something to get it to work?
I would very appreciate an advice on how to get this working!
Environment: Debian-Lenny 64bit
EDIT: The mentioned c++ files are compiling fine with g++ versions v4.2 and v4.3. So I don't think it is a bug in the assembler (from binutils v2.18). Just to be sure I have also tried with binutils v2.20 - but I got the identical error message.
EDIT: I need g++ v4.4.x for the purpose of comparing the output of different g++ versions (and there is no g++ v4.4 in the official lenny repositories)
If your analysis is correct, it seems the proper course of action would be to file a bug for binutils. Or gcc, if it turns out the long symbol names are due to a bug in gcc's name mangling.
Of course, a (preferably reduced) testcase will help the developers fix your problem. Heck, it could have helped SO readers to verify your problems.
You're going to have to compile the corresponding gas instead of depending on what lenny has in his refrigerator (/usr/bin).
Why don't a) upgrade or b) use the backports archive or c) rebuild from current Debian sources on your box? I happily run testing with g++ 4.2, 4.3 and 4.4.
Worst case, you could install a new Debian release in a virtual environment such as a chroot, a Xen or Kvm instance, or inside VirtualBox.

Resources