0

I am trying to upgrade my compiler to support C++11, the kernel of my target machine is 2.6.33.20.

For this purpose I am attempting to use the prebuilt binaries at https://releases.linaro.org/components/toolchain/binaries/, namely the version 5.5.0.

The trivial testing program

//#include <functional>
#include <stdio.h>

int main(void)
{
//  auto lambda = [](int value) { printf("Wert: %d\n", value); };
//  lambda(20);
    printf("My output\n");
    return 0;
}

compiles fine with the command arm-linux-gnueabi-g++ -o test -static-libstdc++ -std=gnu++11 main.cpp.

When I execute file on the executable, it outputs, test: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=2d49dc2492f7fb2ee5992f7614604aac370e42f7, with debug_info, not stripped.

The file command run over the same source but compiled with the old (Pre-C++11) compiler yields: test: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.14, not stripped

The output of readelf -A yields for the old (working) compiler:

Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "ARM10TDMI"
  Tag_CPU_arch: v5T
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-Byte
  Tag_ABI_enum_size: int

whereas the new compiler produced by the new compiler yields:

Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "7-A"
  Tag_CPU_arch: v7
  Tag_CPU_arch_profile: Anwendung
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-2
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_rounding: Needed
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-Byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_CPU_unaligned_access: v6

Following this, I've added the flag -mcpu=arm10tdmi to the above command (resulting in arm-linux-gnueabi-g++ -mcpu=arm10tdmi -o test main.cpp), however the output of readelf still remains the same. Using the ARM flags -march=arm5vt and -mtune=arm10tdmi lead to the exact same result.

This suggests, that the compiler ignores the architecture flags (or maybe does not support building for ARM5) and insists on building for ARM7.

I've also tried the toolchain 4.9, but with the same results.

As a side note: The arm-linux-gnueabi-g++ shipped with Ubuntu 14.04 is known to work (with C++11 support), however I can't seem to find a way to pack the thing into a folder to be used as a transferable toolchain.

Edit: Following old_timer's input, I've redirected the compilation to an object file (main.o) with the command arm-linux-gnueabi-g++ -mcpu=arm10tdmi main.cpp -c

Running readelf -A on the resulting object file yields this output:

Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "ARM10TDMI"
  Tag_CPU_arch: v5T
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-Byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_ABI_optimization_goals: Aggressive Debug

However, when I try to create an actual executable from this using arm-linux-gnueabi-g++ -mcpu=arm10tdmi main.o -o test, the readelf output returns to the ARMv7 output I posted above.

This suggests, that the compiler itself understands and uses the -mcpu switch, but the linker then proceeds and turns it into a ARMv7 binary.

Refugnic Eternium
  • 4,089
  • 1
  • 15
  • 24
  • Did you try running a debugger? – JHBonarius Oct 19 '20 at 06:44
  • @JHBonarius No, not yet. Just the executable. The embedded machine only has gdbserver available, so 'local debugging' is difficult. – Refugnic Eternium Oct 19 '20 at 06:45
  • if you want to use the ubuntu 14.04 compiler it's probably easiest to run it in docker – Alan Birtles Oct 19 '20 at 07:03
  • @AlanBirtles I'd like it best, if I had a toolchain folder, but if all else fails, I'll certainly consider your suggestion. Thank you. – Refugnic Eternium Oct 19 '20 at 07:05
  • 1
    you did some form of make clean to clean up all the objects built before so they are built with the new command line options? – old_timer Oct 20 '20 at 14:05
  • @old_timer I will admit that I have not, however 'make' is not involved in the process at all. There are no intermediate object files either. There is only the source file and the output file 'a.out'. However removing a.out prior to building makes no difference. – Refugnic Eternium Oct 20 '20 at 18:14
  • arm-linux-gnueabi-g++ -c -mcpu=arm10tdmi -o test.o -static-libstdc++ -std=gnu++11 main.cpp works, so if the link doesnt then perhaps the libraries are the problem and overriding the object? – old_timer Oct 20 '20 at 18:28
  • arm-linux-gnueabi-g++ -mcpu=arm10tdmi -save-temps -o test.elf -static-libstdc++ -std=gnu++11 main.cpp same here main.o is arm10tdmi but the output is v7a. need to specify the right library files. – old_timer Oct 20 '20 at 18:30
  • @old_timer On the risk of sounding beyond stupid, but...how would I do that? I was kinda hoping that 'downloading the Linaro toolchain and telling it to compile (and link) an ARM5 binary' would do the trick. – Refugnic Eternium Oct 20 '20 at 18:36
  • If you look at the linker command line from gcc arm-linux-gnueabi/libc/usr/lib/crt1.o, lib/gcc/arm-linux-gnueabi/5.5.0/crtbegin.o, etc these things are all built for v7a and if you disassemble them are thumb/thumb2, so it isnt going to work I dont understand why the linker didnt complain. – old_timer Oct 20 '20 at 18:38
  • I think you have to build from sources for a different target – old_timer Oct 20 '20 at 18:38
  • @old_timer Well, according to the documentation at https://releases.linaro.org/components/toolchain/binaries/5.1-2015.08/ (Supported targets it states 'toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems'). That 'and earlier' would've been mighty nice... – Refugnic Eternium Oct 20 '20 at 18:42
  • I can build bare metal tools but not fully blown linux binary tools. nor C++ tools. in the past there would be a multilib thing or different paths for arm vs thumb for example (different .a files), but that is not jumping out at me doesnt mean they dont have "and earlier" but from what gcc is passing on to the linker on my machine it is all armv7a objects to link in with the arm10tdmi object and for some reason no complaints. – old_timer Oct 20 '20 at 18:54
  • Disassembly of section .text: 000103e0 <_start>: 103e0: f04f 0b00 mov.w fp, #0 103e4: f04f 0e00 mov.w lr, #0 – old_timer Oct 20 '20 at 18:54
  • that is from the binary it built and that is thumb2 code, no way that works on an arm10. – old_timer Oct 20 '20 at 18:55
  • If they imply/claim support then you need to file a ticket there and work through them. That should have been where you started before SO... – old_timer Oct 20 '20 at 18:56
  • You might try crosstool-ng or others if you dont want to just build from sources, directly, yourself. and see what they offer, I pick the target runtime not build time (for gnu tools, for clang/llvm build time) and dont use C or other libraries like that for bare metal so it has been many years over a decade since I tried to do something like that and the biggest problem them was arm vs thumb libraries...you just have to research it I guess or drop your C++11 desire and go back to a tool that builds for the target. – old_timer Oct 20 '20 at 19:01
  • @old_timer Yes, I see. I've just filed a support ticket with the Linaro group, see what they say (you are right of course, I should've done that, when it became apparent that something wasn't working like it's supposed to). Would you mind putting your advice into an answer, so I can accept it? I don't like having unanswered questions, even if I don't necessarily like what they imply. :) – Refugnic Eternium Oct 20 '20 at 19:11

1 Answers1

1

Kudos for this answer to go old_timer, who gave me an invaluable hint on where to go.

All I ended up having to do was mosey over to https://crosstool-ng.github.io, download the package, rummage through the dependencies and then let the thing do it's magic.

I chose the minimal configuration, compiler version 5.5.0 and, despite my worries that Kernel version 2.6.33.20 was not available, the binary simply worked after adding the target architecture to the command line call.

Refugnic Eternium
  • 4,089
  • 1
  • 15
  • 24