arm-none-eabi-ld cannot find -mcpu=cortex-m3 - gcc

There is another question with similar naming but it was never resolved.
I installed arm-none-eabi gcc and binutils from the GNU Arm Embedded PPA on Ubuntu. This toolchain normally works fine.
Today however, in my Makefile, I link with -march=armv7-m -mcpu=cortex-m3 as some of the options. This immediately causes ld to fail like this:
$ arm-none-eabi-ld -mcpu=cortex-m3 -march=armv7-m -Tcm3.ld # and some more options
arm-none-eabi-ld: unrecognised emulation mode: arch=armv7-m
Supported emulations: armelf
What have I done wrong? I can't seem to find any information about this!
I've also tested this with my other toolchain (CodeSourcery, March 2011). That toolchain normally works, but fails now too.
Should I be linking with gcc not ld?

It appears that linking with gcc rather than ld solves the problem. I can even pass in the linker script without having to use -Wl,-T.
I'm still open as to why ld didn't work in the first place.

Related

C compiler for mac?

I'm working through a text on linking, and wanted to work along with some examples in said text.
To better understand whats going on when I invoke the gcc driver, I was looking into doing all the compilation old-school by hand;
preprocessing using cpp
compiling with cc1
assembling with as
linking using ld
Unfortunately, on my Mac I don't seem to be able to reference cc1directly (no listing of cc1 in man). What are my options?
Read some material about GCC internals. First the wikipage on GCC. Then, you could play with the MELT probe (you may want a Linux system to use it).
Then read the GCC manual. And the GCC resource center
Use gcc -v -Wall to compile, it will show what cc1 is running (and -Wall is always useful). So try compiling with gcc -v -Wall hello.c -o helloworld.bin
the cc1 program don't sit in your PATH or in /usr/bin/ but -on my system- in /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1
The command gcc -print-prog-name=cc1 will tell you which cc1 is used by your gcc. See GCC debugging options for more.
The preprocessing is now inside cc1.
The gcc program is just a driver, starting cc1 (which does most of the compiling work), then as, ld etc...
The MELT site contains some documentation, and some slides explaining GCC, which you could find interesting. MELT is a domain specific language to extend GCC.
See also the picture on http://starynkevitch.net/Basile/gcc-melt/cc1-internals.svg and the below picture
picture from http://starynkevitch.net/Basile/gcc-melt/gcc-MELT-inside.png, done by me, CC BY SA
The cc1 is producing a .s assembly file; the as (started by gcc) is transforming it into .o. The ld linker (started by gcc) will produce a library or an executable.
PS. I have a Linux system, but things are very similar on MacOSX.
reference on linking
A good book about linking is Levine's Linkers & loaders book.
PS. MELT is obsolete in 2021, but I am working on the Bismon static source code analyzer and on RefPerSys (which generates C++ code).
For reference, I installed gcc-10 with brew on my macOS (Catalina).
While cc1 is not directly accessible (via PATH), it can be found in
/usr/local/Cellar/gcc/10.2.0/libexec/gcc/x86_64-apple-darwin19/10.2.0
If you are lost, try gcc -v and from the verbose information you may find where your cc1 is.

The program cannot find correct version of glibc/libstdc++, although it was statically linked

I am trying to link my program statically with glibc, because version of the glibc on the target machine is pretty much unpredictable. I used linker flags -static-libgcc and -static-libstdc++ and it worked fine. The executable is big, but I can live with it. Unfortunately, when I run my executable on the target machine (it is named 'mytest' in the example below) I get the following error:
./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by libboost_log.so.1.53.0)
./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by libboost_log.so.1.53.0)
./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by libboost_log.so.1.53.0)
./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by libboost_date_time.so.1.53.0)
./mytest: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by libboost_thread.so.1.53.0)
If I do 'strings' on mytest, it gives me
$ strings mytest | grep GLIBC
GLIBC_2.9
GLIBC_2.7
GLIBC_2.8
GLIBC_2.3.2
GLIBC_2.2.5
GLIBCXX_3.4.15
GLIBCXX_3.4.11
GLIBCXX_3.4.14
GLIBCXX_3.4.9
GLIBCXX_3.4
What means, I think, that the static linking was working ok. Why does the loader still tries to look for my functions in shared glibc and libstdc++? What am I doing wrong?
Thanks!
I am trying to link my program statically with glibc, because version of the glibc on the target machine is pretty much unpredictable. I used linker flags -static-libgcc and -static-libstdc++ and it worked fine.
That didn't affect the version of glibc (libc), which is different from libgcc and libstdc++. With these flags, you still have produced a dynamically-linked executable, which is expected to not work on an older distribution.
You can link your executable with -static flag, and that should give you a completely static executable.
Update:
After re-reading your question; your problem is not with glibc. Your problem is that you are linking with libboost_log.so, which itself depends on libstdc++.so.6.
The answer then is to link with libboost*.a instead of libboost*.so. You can try to achieve it this way:
g++ $(OBJS) -static-libgcc -static-libstdc++ -Wl,-Bstatic -lboost_log ... \
-Wl,-Bdynamic
(It is very important to have the trailing -Wl,-Bdynamic.)
Linking with -static-libgcc and -static-libstdc++ will only work for those libraries. It looks like you are also linking against the boost libraries (likely dynamically) which then link against libgcc and libstdc++.
Try running the following:
ldd mytest
It should show "not a dynamic executable". If it shows anything else, it means it is dynamically linked against other libraries. It doesn't always work so easily, but try adding -static to the compilation line as well to take care of remaining libraries.

GCC - Linking is unsuccessful

and sorry for my not really good english. I'll try my best :)
I am trying to compile a addin for my Casio graphic calculator in C. This works without problems when using the official SDK. Because it is only available for Windows, I want to use gcc.
So I got sh-rtems-gcc and it's binutils from macports and tried to compile my program according to this instructions. I copy-pasted the described addin.ld and crt0.s and placed my main.c and libfxsys.a (from the same guys as the instructions mentioned above) in the same directory. The sub-dir include contains fxsys' headers. I verified the presence of all the functions of the library in the .a file with nm.
When using this command for compilation:
sh-rtems-gcc-4.2.3 -m3 -mb -nostdlib -I./include -c crt0.s main.c
Everything works fine. But then im trying to link:
sh-rtems-gcc-4.2.3 -m3 -mb -nostdlib -L. -o myaddin.elf -Taddin.ld crt0.o main.o -lfxsys
and get the following error:
main.o: In function `__main':
main.c:(.text+0x248): undefined reference to `_Bdisp_AllClr_VRAM'
...
... (--- cut 16 other errors in the same format ---)
...
main.c:(.text+0x360): undefined reference to `_Sleep'
./libfxsys.a(locate.o): In function `_locate':
locate.c:(.text+0x28): undefined reference to `_locate_OS'
collect2: ld gab 1 als Ende-Status zurück
All the missing symbols are in the libfxsys.a. I have verified this with nm.
I have already played with the positions of the library in the command, as this is often mentioned as a source of failure in other posts found in google, but without success. I also tried adding and removing the -lgcc option that is used in the above mentioned instructions, without success.
My Host-Machine is a Intel Mac, OS X 10.6
Because I have no idea how to solve this problem, and get to compile my program, I have to ask: What am I doing wrong? How can I compile my program without using the SDK?
Thanks in advance,
xythobuz
Edit:
I have also tried linking with:
sh-rtems-ld -EB -L. -o myaddin.elf -Taddin.ld crt0.o --start-group main.o libfxsys.a --end-group
But it produces the same output as above.
I can't say the exact problem, but would investigate like this:
Find the library that contains the missing symbols. Use nm to see symbol names
Once you know which library contains the symbols make sure you're linking to it, and in the correct order. Try using recursive symbol resolution options -( -) with your linker.

How to link to a specific version of the standard library (with gcc)

I've installed GCC 3.4 to /opt/gcc-3.4, and I'm using it to compile legacy code which is incompatible with GCC 4. This also means old versions of the C(++) standard libraries, binutils, and utility libraries.
It works fine for some libraries, but fails when compiling libtiff, because it picks up the system libraries in /usr/lib (see output below). This might be an autotools/configure issue, but I'm not sure. I can't find a configure switch or environment variable, and I'd rather not modify my system /usr/lib/libc.so .
So how to make sure it links to the standard library in /opt/gcc-3.4.4/lib, and ignores /lib and /usr/lib completely?
Output of make (excerpt):
libtool: link: g++ -shared -nostdlib /usr/lib/crti.o /opt/gcc-3.4.3/lib/gcc/i686-pc-linux-gnu/3.4.3/crtbeginS.o .libs/tif_stream.o -Wl,--whole-archive ../port/.libs/libport.a -Wl,--no-whole-archive -Wl,-rpath -Wl,/home/jason/d0src34/prereq/tiff-3.9.4/libtiff/.libs -Wl,-rpath -Wl,/opt/gcc-3.4.3/lib -Wl,-rpath -Wl,/home/jason/d0src34/prereq/usr/lib -Wl,-rpath -Wl,/opt/gcc-3.4.3/lib ../libtiff/.libs/libtiff.so -L/usr/lib /usr/lib/libjpeg.so -lz -L/opt/gcc-3.4.3/lib/gcc/i686-pc-linux-gnu/3.4.3 -L/opt/gcc-3.4.3/lib/gcc/i686-pc-linux-gnu/3.4.3/../../.. /opt/gcc-3.4.3/lib/libstdc++.so -L/home/jason/Downloads/gcc-3.4.3/build/i686-pc-linux-gnu/libstdc++-v3/src -L/home/jason/Downloads/gcc-3.4.3/build/i686-pc-linux-gnu/libstdc++-v3/src/.libs -L/home/jason/Downloads/gcc-3.4.3/build/gcc -lm -lc -lgcc_s /opt/gcc-3.4.3/lib/gcc/i686-pc-linux-gnu/3.4.3/crtendS.o /usr/lib/crtn.o -Wl,-soname -Wl,libtiffxx.so.3 -o .libs/libtiffxx.so.3.9.4
/home/jason/d0src34/prereq/usr/bin/ld:/usr/lib/libc.so: file format not recognized; treating as linker script
/home/jason/d0src34/prereq/usr/bin/ld:/usr/lib/libc.so:5: parse error
I've found a (hackish) answer to my own question:
I've been using binutils 2.15, because later versions have an incompatibility with GCC 3.4. In more recent versions, the format of /usr/lib/libc.so has changed, and the old binutils can't parse it.
I temporarily commented out the last line (with "GROUP"), and my code compiled:
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
/* GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) ) */
However, I'm not really satisfied, since I can hardly tell other people who want to use the code to edit their system files. Also, I'm not sure if I've linked it to the correct glibc version, since the system /usr/lib is still in the search path, so I can't tell for sure if the binaries will work on other systems.

shared library locations for matlab mex files:

I am trying to write a matlab mex function which uses libhdf5; My Linux install provides libhdf5-1.8 shared libraries and headers. However, my version of Matlab, r2007b, provides a libhdf5.so from the 1.6 release. (Matlab .mat files bootstrap hdf5, evidently). When I compile the mex, it segfaults in Matlab. If I downgrade my version of libhdf5 to 1.6 (not a long-term option), the code compiles and runs fine.
question: how do I solve this problem? how do I tell the mex compilation process to link against /usr/lib64/libhdf5.so.6 instead of /opt/matlab/bin/glnxa64/libhdf5.so.0 ? When I try to do this using -Wl,-rpath-link,/usr/lib64 in my compilation, I get errors like:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../x86_64-pc-linux-gnu/bin/ld: warning: libhdf5.so.0, needed by /opt/matlab/matlab75/bin/glnxa64/libmat.so, may conflict with libhdf5.so.6
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
mex: link of 'hdf5_read_strings.mexa64' failed.
make: *** [hdf5_read_strings.mexa64] Error 1
ack. the last resort would be to download a local copy of the hdf5-1.6.5 headers and be done with it, but this is not future proof (a Matlab version upgrade is in my future.). any ideas?
EDIT: per Ramashalanka's excellent suggestions, I
A) called mex -v to get the 3 gcc commands; the last is the linker command;
B) called that linker command with a -v to get the collect command;
C) called that collect2 -v -t and the rest of the flags.
The relevant parts of my output:
/usr/bin/ld: mode elf_x86_64
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crti.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/crtbeginS.o
hdf5_read_strings.o
mexversion.o
-lmx (/opt/matlab/matlab75/bin/glnxa64/libmx.so)
-lmex (/opt/matlab/matlab75/bin/glnxa64/libmex.so)
-lhdf5 (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/libhdf5.so)
/lib64/libz.so
-lm (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/libm.so)
-lstdc++ (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libstdc++.so)
-lgcc_s (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libgcc_s.so)
/lib64/libpthread.so.0
/lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
-lgcc_s (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libgcc_s.so)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/crtendS.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crtn.o
So, in fact the libhdf5.so from /usr/lib64 is being referenced. However, this is being overriden, I believe, by the environment variable LD_LIBRARY_PATH, which my version of Matlab automagically sets at run-time so it can locate its own versions of e.g. libmex.so, etc.
I am thinking that the crt_file.c example works either b/c it does not use the functions I am using (H5DOpen, which had a signature change in the move from 1.6 to 1.8 (yes, I am using -DH5_USE_16_API)), or, less likely, b/c it does not hit the parts of Matlab internals that need hdf5. ack.
The following worked on my system:
Install hdf5 version 1.8.4 (you've already done this: I installed the source and compiled to ensure it is compatible with my system, that I get gcc versions and that I get the static libraries - e.g. the binaries offered for my system are icc specific).
Make a target file. You already have your own file. I used the simple h5_crtfile.c from here (a good idea to start with this simple file first a look for warnings). I changed main to mexFunction with the usual args and included mex.h.
Specify the static 1.8.4 library you want to load explicitly (the full path with no -L for it necessary) and don't include -lhdf5 in the LDFLAGS. Include a -t option so you can ensure that there is no dynamic hdf5 library being loaded. You also need -lz, with zlib installed. For darwin we also need a -bundle in LDFLAGS:
mex CFLAGS='-I/usr/local/hdf5/include' LDFLAGS='-t /usr/local/hdf5/lib/libhdf5.a -lz -bundle' h5_crtfile.c -v
For linux, you need an equivalent position-independent call, e.g. fPIC and maybe -shared, but I don't have a linux system with a matlab license, so I can't check:
mex CFLAGS='-fPIC -I/usr/local/hdf5/include' LDFLAGS='-t /usr/local/hdf5/lib/libhdf5.a -lz -shared' h5_crtfile.c -v
Run the h5_crtfile mex file. This runs without problems on my machine. It just does a H5Fcreate and H5Fclose to create "file.h5" in the current directory, and when I call file file.h5 I get file.h5: Hierarchical Data Format (version 5) data.
Note that if I include a -lhdf5 above in step 3, then matlab aborts when I try to run the executable (because it then uses matlab's dynamic libraries which for me are version 1.6.5), so this is definitely solving the problem on my system.
Thanks for the question. My solution above is definitely much easier for me than what I was doing before. Hopefully the above works for you.
I am accepting Ramashalanka's answer because it led me to the exact solution which I will post here for completeness only:
download the hdf5-1.6.5 library from the hdf5 website, and install the header files in a local directory;
tell mex to look for "hdf5.h" in this local directory, rather than in the standard location (e.g. /usr/include.)
tell mex to compile my code and the shared object library provided by matlab, and do not use the -ldfh5 flag in LDFLAGS.
the command I used is, essentially:
/opt/matlab/matlab_default/bin/mex -v CC#gcc CXX#g++ CFLAGS#"-Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include" CXXFLAGS#"-Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include " -O -lmwblas -largeArrayDims -L/usr/lib64 hdf5_read_strings.c /opt/matlab/matlab_default/bin/glnxa64/libhdf5.so.0
this gets translated by mex into the commands:
gcc -c -I/opt/matlab/matlab75/extern/include -DMATLAB_MEX_FILE -Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include -O -DNDEBUG hdf5_read_strings.c
gcc -c -I/opt/matlab/matlab75/extern/include -DMATLAB_MEX_FILE -Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include -O -DNDEBUG /opt/matlab/matlab75/extern/src/mexversion.c
gcc -O -pthread -shared -Wl,--version-script,/opt/matlab/matlab75/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -o hdf5_read_strings.mexa64 hdf5_read_strings.o mexversion.o -lmwblas -L/usr/lib64 /opt/matlab/matlab_default/bin/glnxa64/libhdf5.so.0 -Wl,-rpath-link,/opt/matlab/matlab_default/bin/glnxa64 -L/opt/matlab/matlab_default/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++
this solution should work on all my various target machines and at least until I upgrade to matlab r2009a, which I believe uses hdf5-1.8. thanks for all the help, sorry for being so dense with this--I think I was overly-committed to using the packaged version of hdf5, rather than a local set of header files.
Note this would all have been trivial if Mathworks had provided a set of the header files with the Matlab distribution...

Resources