Compile glibc for ARMv7 without THUMB? - gdb

I am teaching a class in ARMv7 assembly language and would like to show how to use GDB. Unfortunately, my distribution (Linux cptr280 5.15.0-1017-raspi #19-Ubuntu SMP PREEMPT Fri Oct 14 08:24:06 UTC 2022 armv7l armv7l armv7l GNU/Linux) does not work with the C library. If I link for dynamic libraries, then we can't step past _setup (which seems to be at /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3; see here). If I link libc using -static then I can debug my program until it tries to make a call to the C library. At that point it seems to switch to THUMB mode and GDB reports an illegal instruction.
Any advice is appreciated. My current theory is to try to compile libc from sources and configure it to avoid THUMB mode, but I don't know how to do that.

Related

Linking MKL library in C++

I'm having a lot of trouble linking the Intel MKL libraries to my code in C++. I downloaded the MKL library from this link:
https://software.intel.com/content/www/us/en/develop/tools/math-kernel-library/choose-download/windows.html
Then it says to use MKL Link Line Advisor to obtain the proper compiler options, which I'm having a lot of trouble figuring out. For reference, I'm using Windows, g++ 8.1.0 and MinGW-W64. Here is part by part:
Intel product: Intel MKL 2020, since I just downloaded it.
OS: Windows, no issues there.
Compiler: Intel(R) Fortran? I'm using g++ to compile my C++ code, so
I have no idea since that option is not available. Doing some
research in stackoverflow, it seems the right choice is Intel(R)
Fortran
Architecture: Intel(R) 64, since I have a 64-bit OS?
Dynamic/Static Linking: Static linking I guess?
Interface layer: 64-bit, since I have a 64-bit OS?
Threading layer: OpenMP, since my current C++ code uses -fopenmp?
OpenMP library: Intel(R) libiomp5. Only one option, so no issues
here.
Fortran95 Interfaces: BLAS95 and LAPACK95
The above choices give me the following compiler options
/4I8 /module:"%MKLROOT%"\include\intel64/ilp64 -I"%MKLROOT%"\include
And this results in error from the compiler:
/4I8: No such file or directory
Can somebody help me please?
I think you should use -DMKL_ILP64 -I"%MKLROOT%"\include for g++.
You should definitely not pick Intel(R) Fortran for the compiler since you are not compiling Fortran programs.

Docker Centos, Cannot Execute Binary File

I have one C++ binary which is running smoothly on local centos. Recently, I started learning docker and trying to run my C++ application on centos docker.
Firstly, I pulled centos:latest from docker hub and installed my C++ application on it and it ran successfully, without any issue. Now i installed docker on raspberry-pi and pulled centos again and tried to ran the same application on it but it gave me error.
bash : cannot execute binary file
Usually, this error comes when we try to run application on different architecture then the one they are built on. I checked cat etc/centos-release on raspberry-pi and result is CentOS Linux release 7.6.1810 (AltArch),where as result on local centos is CentOS Linux release 7.6.1810 (Core)
uname -a on both devices is as follows
raspberry-pi, centos docker Linux c475f349e7c2 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7l armv7l armv7l GNU/Linux
centos, centos docker Linux a57f3fc2c1a6 4.15.0-46-generic #49-Ubuntu SMP Wed Feb 6 09:33:07 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
EDIT:
Also, file myapplication
TTCHAIN: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.24, BuildID[sha1]=287b501c8206893f7819f215ee0033586212b143, with debug_info, not stripped
My question is how can i ran the same native application of centos, pulled from docker on raspberry-pi model 3.
Your application has been built for x86-64. Intel x86-64 binaries CAN NOT run on an ARM processor.
You have two paths to pursue:
If you don't have source code for the application, you will need an x86-64 emulator that will run on your Raspberry Pi. Considering the Pi's lesser capabilities and Intel's proclivity to sue anyone who creates an emulator for their processors, I doubt you'll find one that's publicly available.
If you have the source code for the application, you need to rebuild it as a Raspberry Pi executable. You seem to know that it was written in C++. GCC and other toolchains are available for the Raspberry Pi (most likely a "yum install gcc" on your Pi will grab the compiler and tools for you). Building the application should be extremely similar to building it for x86_64.
You could find a cross-compiler that would let you build for the Pi from your x86_64 box, but that can get complicated.
Could be that you are trying to run a 64-bit binary on a 32-bit processor, would need more information to know for sure though.
You can check by using the file command in the shell. You may have to re-compile on the original system with the -m32 flag to gcc.
Please do a "uname -a" on both devices and post the results.
Most likely the processor or library type doesn't match.
I presume (hope) you're not trying to run an x86-compiled app on a Pi. Although Docker is available for both processor types, Docker will not run x86 binaries on Pi or vice versa.
Actually, AltArch currently means one of the following architectures... ppc64, ppc64le, i386, armhfp (arm v7 32-bit), aarch64 (arm v8 64-bit). Core suggests the mainstream x86 and x86_64 builds of CentOS.
Yep, I bet that's what it is...you can't just transfer an x86 binary to a Raspbian and expect it to work. The application must be rebuilt for the platform.

How to reduce the C++ standard library libstdc++.so file size

I have different C++ compilers on my computer, each compiler has its own libstdc++.so and their size is different.
-rwxr-xr-x. 1 root root 967K Mar 22 2017 libstdc++.so.6.0.13
-rwxr-xr-x. 1 root root 6.5M Aug 1 2017 libstdc++.so.6.0.20
-rwxr-xr-x. 1 root root 11M Aug 1 2017 libstdc++.so.6.0.21
-rwxr-xr-x. 1 root root 12M Jan 30 16:58 libstdc++.so.6.0.24
I want to know why libstdc++.so.6.0.13 is so much smaller than others, and is there any way to reduce others' size.
I will be glad if some one can help me.
The versioning scheme of libstdc++ is misleading, the differences between these versions are actually huge when you consider the corresponding GCC versions:
GCC 4.4.2: libstdc++.so.6.0.13 (October 15, 2009)
GCC 4.9.0: libstdc++.so.6.0.20 (April 22, 2014)
GCC 5.1.0: libstdc++.so.6.0.21 (April 22, 2015)
GCC 7.2.0: libstdc++.so.6.0.24 (August 14, 2017)
There's been the C++14 implementation between GCC 4.4 and 4.9, and major work on C++17 and various experimental proposals after that.
From libstdc++'s FAQ:
Usually the size of libraries on disk isn't noticeable...
. . . the object files
in question contain template classes and template functions,
pre-instantiated, and splitting those up causes severe maintenance
headaches.
So in short - not much can be done about the size. If you're really interested, you can see what's inside using readelf -a libname.so
You can always downgrade to an older GCC version which will come with a smaller libstdc++.
Having said that, on Ubuntu the size of libstdc++.so.6.0.24 is 1.54MB, so it didn't actually grow that much. There could be something wrong with your specific distro or maybe you grabbed a debug version. You can try stripping debug symbols with strip libstdc++.so.6.0.24 (the strip utility is part of binutils).

crosscompile c++ binary for Amazon EC2

I tried to just compile on what appears to be similar (both Ubuntu 64bit) but the binary is not runnable by the Amazon instance of Ubuntu (which is 64 bit too, but don't know much more than that).
I've seen a thread suggesting spinning additional EC2 instance just to compile there, but it isn't a solution as I can't transfer sources outside, only a compiled binaries and dynamic libs.
Was thinking about making a virtual environment on my computer to spawn a clone of EC2 to compile there, but is it doable?
kernel info:
uname -a
4.4.0-93-generic #116-Ubuntu SMP Fri Aug 11 21:17:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
ip-xxx-xxx-xxx-xxx 4.4.0-1035-aws #44-Ubuntu SMP Tue Sep 12 17:27:47 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
it uses some amazon tailor made kernel it seems?
file info:
file ./testBinary
./testBinary: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), too many program (2304)
file -Pelf_phnum=3000 ./testBinary
./testBinary: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), corrupted program header size, corrupted section header size
You can't really 'clone' EC2 instance that you've created from some AMI. So since you don't have any details about why exactly your library wasn't working, I would suggest running Amazon Linux instead of Ubuntu.
You can run Amazon Linux in a Docker container on your machine and build your library there (https://hub.docker.com/_/amazonlinux/). That way the library should run without problems in any EC2 with Amazon Linux.
If you want to stick with Ubuntu, at the very least you should match Ubuntu versions (not just architecture) and probably kernel versions.

Glibc vs GCC vs binutils compatibility

Is there a sort of official documentation about version compatibility between binutils, glibc and GCC? I found this matrix for binutils vs GCC version compatibility. It would be good to have something like this for GCC vs glibc as well.
The point I'm asking this for is that I need to know if I can build, say, cross GCC 4.9.2 with "embedded" glibc 2.2.4 to be able to support quite old targets like CentOS 5.
Thank you.
it's extremely unlikely you'll be able to build such an old version of glibc with such a new version of gcc. glibc documents the min required version of binutils & gcc in its INSTALL file.
glibc-2.23 states:
Recommended Tools for Compilation
GCC 4.7 or newer
GNU 'binutils' 2.22 or later
typically if you want to go newer than those, glibc will generally work with the version of gcc that was in development at the time of the release. e.g. glibc-2.23 was released 18 Feb 2016 and gcc-6 was under development at that time, so glibc-2.23 will work with gcc-4.7 through gcc-6.
so find the version of gcc you want, then find its release date, then look at the glibc releases from around the same time.
all that said, using an old version of glibc is a terrible idea. it will be full of known security vulnerabilities (include remotely exploitable ones). the latest glibc-2.23 release for example fixed CVE-2015-7547 which affects any application doing DNS network resolution and affects versions starting with glibc-2.9. remember: this is not the only bug lurking.
When building a cross-compiler there are at least two, and sometimes three, platform types to consider:
Platform A is used to BUILD a cross compiler HOSTED on Platform B which TARGETS binaries for embedded Platform C. I used the words BUILD, HOSTED, and TARGETS intentionally, as those are the options passed to configure when building a cross-GCC.
BUILD PLATFORM: Platform of machine which will create the cross-GCC
HOST PLATFORM: Platform of machine which will use the cross-GCC to create binaries
TARGET PLATFORM: Platform of machine which will
run the binaries created by the cross-GCC
Consider the following (Canadian Cross Config, BUILD != HOST platform):
A 32-bit x86 Windows PC running the mingw32 toolchain will be used to compile a cross-GCC. This cross-GCC will be used on 64-bit x86 Linux computers. The binaries created by the cross-GCC should run on a 32-bit PowerPC single-board-computer running LynxOS 178 RtOS (Realtime Operating System).
In the above scenario, our platforms are as follows:
BUILD: i686-w32-mingw32
HOST: x86_64-linux-gnu
TARGET: powerpc-lynx-lynxos178
However, this is not the typical configuration. Most often BUILD PLATFORM and HOST PLATFORM are the same.
A more typical scenario (Regular Cross Config, BUILD == HOST platform):
A 64-bit x86 Linux server will be used to compile a cross-GCC. This cross-GCC will also be used on 64-bit x86 Linux computers. The binaries created by the cross-GCC should run on a 32-bit PowerPC single-board-computer running LynxOS 178 RtOS (Realtime Operating System).
In the above scenario, our platforms are as follows:
BUILD: x86_64-linux-gnu
HOST: x86_64-linux-gnu
TARGET: powerpc-lynx-lynxos178
When building the cross-GCC (assuming we are building a Regular Cross Config, where BUILD == HOST Platform), native versions of GNU BinUtils, GCC, glibc, and libstdc++ (among other libraries) will be required to actually compile the cross-GCC. It is less about specific versions of each component, and more about whether each component supports the specific language features required to compile GCC-4.9.2 (note: just because GCC-4.9.2 implements language feature X, does not mean that language feature X must be supported by the version of GCC used to compile GCC-4.9.2. In the same way, just because glibc-X.X.X implements library feature Y, does not mean that the version of GCC used to compile glibc-X.X.X must have been linked against a glibc that implements feature Y.
In your case, you should simply build your cross-GCC 4.9.2 (or if you are not cross compiling, i.e. you are compiling for CentOS 5 on Linux, build native GCC 4.9.2), and then when you link your executable for CentOS 5, explicitly link glibc v2.2.4 using -l:libc.so.2.2.4. You also probably will need to define -std=c99 or -std=gnu99 when you compile, as I highly doubt glibc 2.2.4 supports the C 2011 standard.