gdb ARM Cortex-M exception Unwinding - debugging

I have been working with some Cortex-M4 (Freescale K60) devices with a compiled by me GCC (v4.7.2), BinUtils (v2.22), Newlib (v1.20) and GDB (v7.5). I have always been annoyed by GDB's inability to unwind from hard exceptions.
recently I had an opportunity to use FreeScale's CodeWarrior, where I loaded my binary for debug (compiled by my tools), and it could unwind the exception. It looks like CodeWarrior is running GDB v7.4.1 under the hood. Is there some patch I missed for GDB, or some configure option?
Here is the script used to build GDB:
TOOLCHAIN=gdb-7.5
mkdir -p BUILD/gdb
cd BUILD/gdb
../../${TOOLCHAIN}/configure --prefix=${PREFIX} --target=${TARGET} --enable-interwork --enable-multilib --with-expat=yes --with-python --without-auto-load-safe-path 2>&1 | tee configure.out
make all install
cd ../../
Thanks!

GDB can do Cortex M profile exception unwinding, once you tell it that the target is actually Cortex M profile using a Target Description XML with correct Feature.
This can be done via the set target tdesc <filename> command, but newer gdb servers (e.g. OpenOCD) should do so already.

Related

Why is gdbserver not found when using the Linaro external toolchain in Buildroot?

I am using Buildroot 2018.02 for an IMX6 board and the Linaro external toochain 2017.11 based on GCC 2017.11 (GCC 7.2.1)
Now i am adding some debug tools such as gdbserver on the target.
Everything is OK if i use the option "Build cross gdb for the host" and selecting the gdb debugger version 7.11.x for the host along with the gdbserver (BR2_PACKAGE_GDB_SERVER) in the "Target Packages > Debugging,.." menu. There are also other version of gdb available in Buildroot such as 7.12.x and 8.0.x.
However, for an external toolchain the recommended way is :
https://github.com/mbats/eclipse-buildroot-bundle/wiki/Tutorial-:-How-to-debug-a-remote-application-%3F which means to activate only the "Copy gdb server to the Target" option in Buildroot (although the post is a bit old)
I have noticed that the BR2_TOOLCHAIN_EXTERNAL_LINARO_ARM description says that Linaro gdb is based on gdb 8.0 so a newer version that the one i am using (7.11.x).
But when i do that, i have the following message on the target board :
# gdbserver
-sh: gdbserver: not found
despite the following :
# which gdbserver
/usr/bin/gdbserver
gdbserver binary is on the target.
How to fix this in Buildroot ?
Moreover i have two additional questions :
Does it really matter to have the Linaro toolchain gdb instead of
the gdb 7.11.x that works "out of the box" in my case ?
If i don't use the Linaro gdb then should i use the gdb version
8.0.x ( because the Linaro version is based on the 8.0 of GDB ) ?
Thank you for your help.
The gdbserver binary in the Linaro 2017.11 toolchain is broken: it requests /usr/lib/ld.so.1 as the program interpreter (see below), but that program interpreter doesn't exist.
You can try to create a symlink /usr/lib/ld.so.1 -> /lib/ld-linux-armhf.so.3 (add that to your filesystem overlay if it works). Alternatively, you can specify the program interpreter explicitly by putting it before the executable, i.e. /lib/ld-linux-armhf.so.3 /usr/bin/gdbserver.
The "program interpreter" is a parameter of an ELF file that points to a program that is used to load the ELF file into memory and to start executing it. The main responsibility of the program interpreter is to find and load the dynamic libraries that the program needs. Thus, it is usually called the "dynamic library loader", or ld.so. It is built and installed together with the toolchain - specifically, the standard C library (glibc). When a program is linked, the linker will also set the program interpreter (it is copied from libc.so). Apparently Linaro did something really peculiar to end up with a wrong program interpreter in the gdbserver executable.
# gdbserver
-sh: gdbserver: not found
depsite the following :
# which gdbserver
/usr/bin/gdbserver
Most likely:
The gdbserver is a dynamically linked binary, and
The ELF interpreter that this binary is linked to use is not present on the target system.
Use readelf -l /usr/bin/gdbserver | grep -i interpreter to find out what runtime loader this gdbserver requires. Verify that that file is not present on the target. Copy it to the target and enjoy.

gdbserver: Target description specified unknown architecture "aarch64"

I try to use remotely the gdbserver for debug as follows
Start the gdbserver on target machine
$ gdbserver localhost:2000 hello -l 20 -b 10 --enable-targets=all
Host machine has the program binary with debugging enabled
"copied binary from ARM target to host"
Run gdb on host machine
$ gdb -q --args hello --enable-target=all
Connect to the target
(gdb) target remote 192.168.15.132
192.168.15.132: No such file or directory.
(gdb) target remote 192.168.15.132:2000
Remote debugging using 192.168.15.132:2000
warning: while parsing target description (at line 11): Target description specified unknown architecture "aarch64"
warning: Could not load XML target description; ignoring
Remote register badly formatted: T051d:0000000000000000;1f:80fcffffffff0000;20:403cfdb7ffff0000;thread:pd60.d60;core:1;
here: 00000000;1f:80fcffffffff0000;20:403cfdb7ffff0000;thread:pd60.d60;core:1;
(gdb) q
I am looking for an advice to correctly debug with ARM remote target.
To debug executables compiled for a different architecture, install gdb-multiarch and run gdb-multiarch instead of gdb. Different distributions compile gdb differently and some even lack the multiarch version in their repositories - RHEL doesn't include it, but it's present in Ubuntu and Debian.
Since you are reporting that your GDB supports the following architectures:
i386:x64-32 i386:x86-64:intel i386 i386:x64-32:intel i386:x86-64:nacl i386:intel i386:x64-32:nacl i8086 i386:nacl i386:x86-64, you may be attempting to remotely debug an aarch64-linux-gnu executable using an x86_64-targeted version of gdb.I would suggest to download/install gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz:
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz
tar Jxvf gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz -C /opt
and then use /opt/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gdb for remotely debugging your program.

Building binutils-2.31.1: No linker produced

As part of trying to build a gcc 8.2 cross-compiler (targeting ia64-hp-hpux11.31), I'm running into problems building binutils 2.31.1. The build actually seems to complete just fine. I end with a bunch of binaries (ar, objdump, strings, etc.), but some important ones like as and ld are missing. I think I configured binutils properly, explicitely enabling ld and disabling gold: ../binutils-2.31.1/configure --target=ia64-hp-hpux11.31 --enable-ld=yes --enable-gold=no.
I scanned through the stdout + stderr output of the entire build process, but didn't find any hints. The only suspicous thing is that configure outputs: checking whether we are cross compiling... no. Shouldn't that say yes, since I'm building for cross compilation? If my understanding of how --build, --host and --target work is correct, shouldn't that imply cross compilation?
I should note this is my first time trying to build a cross-compiler. I should also note that my Linux "machine" is Ubuntu 16.04.2 LTS under the Windows Subsystem for Linux, perhaps this has something to do with it.
My config.log
See the configure script at line 3744:
ia64*-**-hpux*)
# No ld support yet.
noconfigdirs="$noconfigdirs gdb libgui itcl ld"
;;
That causes the ld directory to be skipped during the build.
You should have an assembler though, built as gas/as-new (after make install that will get installed as ia64-hp-hpux11.31-as).

Can we have a compiler running in embedded device

It may sound weird but I would like to know if we can have compiler in embedded device (lets say gcc support on imx6).
Of course, it is not uncommon to have target tools, but is is not trivial. A non-native (from the host perspective) compiler must be cross-compiled for the target architecture. You didn't provide any details, but maybe your build system can build target tools for you. Of course, you need much more than just a compiler. You probably need make, autotools, and probably more. It depends on what you are trying to compile on the target.
Your best bet would be to gain some proficiency using a cross-compiler environment. If you haven't already, you might check out the Yocto Project. It supports i.mx6 (and much more) and probably provides a path to get target tools on your board.
Good luck!
To arm arch, it will be easy to get target compiler, linaro ubuntu of linaro project will provide a completely solution for arm arch, it can provide GNOME desktop、toolchain and informative tools on your target.
You can get more info from the following link:
https://wiki.linaro.org/Platform/DevPlatform/Ubuntu
Yes that should easy enough.. What version of cross-compiler do you have in your machine, download the matching gcc compiler from here https://ftp.gnu.org/gnu/gcc/
Now what you want to do is cross-compile the GCC which you downloaded using the crosscompiler which you already have.
Following is an example of compiling 4.7.4, NOTE: replace the HOST and BUILD according to your platform:
./contrib/download_prerequisites
cd ..
mkdir objdir
cd objdir
../gcc-4.7.4/configure --build=$BUILD \
--host=$HOST \
--target=$HOST \
--prefix=/usr \
--disable-nls \
--enable-languages=c,c++ \
--with-float=hard
make -j $JOBS
make DESTDIR=<path_where_to_install> install

Building GCC on OS X 10.11

Building GCC (latest revision) on OS X 10.11.1 here, using the command line:
../gccx/configure --with-gmp="/opt/local" --with-mpfr="/opt/local" \
--with-mpc="/opt/local" --with-libiconv-prefix="/opt/local" --with-pkgversion="GCCX" \
--program-transform-name='s/^gcc$/gccx/; s/^g++$/g++x/' --enable-languages=c
Followed build instructions exactly, and getting this error:
g++ -std=gnu++98 -g -DIN_GCC -fno-strict-aliasing
-fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wno-format -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fno-common -DHAVE_CONFIG_H -DGENERATOR_FILE -fno-PIE -Wl,-no_pie -o build/genmatch \
build/genmatch.o ../build-x86_64-apple-darwin15.0.0/libcpp/libcpp.a build/errors.o build/vec.o build/hash-table.o ../build-x86_64-apple-darwin15.0.0/libiberty/libiberty.a Undefined symbols for architecture x86_64: "_iconv", referenced from:
convert_using_iconv(void*, unsigned char const*, unsigned long, _cpp_strbuf*) in libcpp.a(charset.o)
(maybe you meant: __Z14cpp_init_iconvP10cpp_reader, __cpp_destroy_iconv ) "_iconv_close", referenced from:
__cpp_destroy_iconv in libcpp.a(charset.o)
__cpp_convert_input in libcpp.a(charset.o) "_iconv_open", referenced from:
init_iconv_desc(cpp_reader*, char const*, char const*) in libcpp.a(charset.o) ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make[3]: *** [build/genmatch] Error 1 make[2]: *** [all-stage1-gcc] Error 2 make[1]: *** [stage1-bubble] Error 2 make:
*** [all] Error 2
(A complete log is available at https://gist.github.com/3cb5d044533e657f4add.)
After investigating gcc/Makefile, it seems that the BUILD_CPPLIB variable does not include $(LIBICONV), since it is in a stage1 bootstrap at the time of the error. The relevant section is preceded by
# For stage1 and when cross-compiling use the build libcpp which is
# built with NLS disabled. For stage2+ use the host library and
# its dependencies.
Yet clearly the stage1 build of build/genmatch is referencing libcpp, which uses symbols from libiconv. So something is amiss here.
How can I fix it?
General discussion
Building GCC on Mac OS X is an occasionally fraught process. I've had various issues with various versions of GCC and various versions of Mac OS X over the years. You can see an earlier explanation of what I did in Install GCC on Mac OS X — that was for building GCC 4.8.x on Mavericks 10.9.x (or possibly Mountain Lion 10.8.x); it also reports success building GCC 4.9.0 on Mavericks 10.9.x, but failure to do so on Yosemite 10.10.x.
This is an updated recipe for building GCC 5.2.0 on Mac OS X 10.11.1 El Capitan.
It starts off using XCode 7.1.1 — I don't know which other versions of XCode are OK.
Note that El Capitan has a feature SIP (System Integrity Protection) that was not in Yosemite and earlier versions. This means you cannot create arbitrary directories under /usr any more. I used to install in /usr/gcc/vX.Y.Z; that is no longer permitted in El Capitan. One major change, therefore, is that I now install in /opt/gcc/v.X.Y.Z.
I've found that having DYLD_LIBRARY_PATH set is problematic — especially on El Capitan. In a major break from the past, I'm now not setting that at all. Note that the scripts unset it. Note too that the script explicitly sets the phase 1 compilers CC and CXX to /usr/bin/clang and /usr/bin/clang++ respectively (the XCode compilers). The current versions of GCC require a capable C++ compiler instead of (or as well as) a C compiler.
I have occasionally had problems with libiconv, but at the moment I've evaded them by not having my own version installed. Similarly, I've occasionally had problems with some awk scripts in the GCC source. I had to hack it/them to get it to work OK. However, with release copy of GCC 5.2.0 source, I seem to be able to build directly out of the box.
If you've only got a single disk partition, this next point isn't crucial. If you have multiple disks, either make sure the target directory does not exist or ensure that its name is exactly what you want. On the machines at work (not Macs but Linux machines, etc), I still use /usr/gcc/vX.Y.Z as the 'official' install location, but the software ends up in some arbitrary file system where there's enough space, such as /work4/gcc, and eventually there is a symlink such that /usr/gcc/vX.Y.Z gets to /work4/gcc/vX.Y.Z. However, it is crucial that /work4/gcc/vX.Y.Z does not exist while GCC is being compiled because it will resolve the name via realpath() or its equivalent and embed /work4/gcc/vX.Y.Z into the binaries, rather than the neutral name /usr/gcc/vX.Y.Z. This limits the portability of the installation; any other machine that it is moved to has to have a directory /work4/gcc/vX.Y.Z, even though you asked to install it in /usr/gcc/vX.Y.Z.
Compiling GCC 5.2.0 on Mac OS X 10.11.1 with XCode 7.1.1
I had to work with down-versions of both GMP (5.1.3 instead of 6.0.0a) and ISL (0.14 instead of 0.15). The builds for the later versions both caused me trouble.
Note that I put the library code for GMP, MPC, MPFR, ISL and Cloog (see the GCC pre-requisites) in the GCC source directory so that GCC builds its own versions of these libraries. I've found that its the simplest way to ensure that GCC locates these libraries correctly.
Target directory: /opt/gcc/v5.2.0
Build time was about 2h 15m on a 17" MacBook Pro (early 2011) running Intel Core i7 at 2.3 GHz, with 16 GiB 1333 MHz DDR3 main memory, and a 750 GB 5400 rpm hard disk drive. The source occupies about 850 MiB; the build tree ends up at about 4.6 GiB — you need plenty of disk space. The installed code ends up at about 420 MiB.
Script used — extract-gcc-5.2.0.sh
#!/bin/bash
unset DYLD_LIBRARY_PATH
TAR=tar
VER_NUM=5.2.0
GCC_VER=gcc-${VER_NUM}
TGT_BASE=/opt/gcc
TGT_DIR=${TGT_BASE}/v${VER_NUM}
CC=/usr/bin/clang
CXX=/usr/bin/clang++
extract() {
echo "Extract $1"
$TAR -xf $1
}
if [ ! -d "$GCC_VER" ]
then extract ${GCC_VER}.tar.bz2 || exit 1
fi
(
cd ${GCC_VER} || exit
nbncl <<EOF |
cloog 0.18.1 tar.gz
gmp 5.1.3 tar.xz
# gmp 6.0.0 tar.lz
isl 0.14 tar.bz2
# isl 0.15 tar.bz2
mpc 1.0.3 tar.gz
mpfr 3.1.3 tar.xz
EOF
while read file vrsn extn
do
tarfile="../$file-$vrsn.$extn"
if [ ! -f "$tarfile" ]
then echo "Cannot find $tarfile" >&2; exit 1;
fi
if [ ! -d "$file-$vrsn" ]
then
(
set -x
extract "$tarfile" &&
ln -s "$file-$vrsn" "$file"
) || exit 1
fi
done
)
if [ $? = 0 ]
then
mkdir ${GCC_VER}-obj
cd ${GCC_VER}-obj
../${GCC_VER}/configure --prefix="${TGT_DIR}" \
CC="${CC}" \
CXX="${CXX}"
make -j8 bootstrap
fi
Script nbncl — non-blank, non-comment lines
#!/usr/bin/env perl
#
# Non-blank, non-comment lines only
use warnings;
use strict;
while (<>)
{
chomp;
s/\s+$//;
s/\s*#.*$//;
print "$_\n" unless /^$/;
}
First, see Jonathan Leffler's very complete answer. I have a few more suggestions here.
The gcc configuration and build process needs to find your system's native header files and C run-time libraries. Newer, clang-based versions of Xcode hide these pretty deeply, and older versions of gcc don't seem to know how to find them. To get gcc 4.6 to build at all, I had to create these symlinks:
ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include /usr
ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/lib/dylib1.10.5.o /usr/local/lib
ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/lib/crt1.10.5.o /usr/local/lib
ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/lib/bundle1.o /usr/local/lib
Your mileage will likely vary slightly: note that those pathnames underneath /Applications/Xcode.app/Contents have various version numbers baked in to them, which are likely to be different on your system.
(If, as Jonathan describes, the newest versions of MacOS don't allow you to put anything in /usr, you might have to create the /usr/include symlink in /usr/local/include, instead, and I suspect that would work, too.)
Also, this is mentioned elsewhere, but it's an unusual requirement, and easy to overlook: do not try to build gcc within its own source tree. Always create a build directory which is a parallel sibling, not a child underneath, of the directory into which you've extracted the gcc sources. That is, do not do this:
tar xzf gcc-x.y.z.tar.bz2
cd gcc-x.y.z # WRONG
mkdir build
cd build
../configure # WRONG
make
Instead, do this:
tar xzf gcc-x.y.z.tar.bz2
mkdir build
cd build
../gcc-x.y.z/configure
make
This is counterintuitive, I know, and it's not the way a lot of other packages work, but it definitely does work for gcc, and it's the recommended way to do it.
Another point: if you discover that your build is failing because you configured it improperly, such that you have to rerun configure with different options, it's safer to delete your entire build directory and start from scratch. The configure and build system sometimes, but it seems not 100% reliably, detects what might need rebuilding in that case. (Deleting and starting over is frustrating, I agree, but again, it can really save time in the long run.)
Finally, if you're trying to build a cross-compiler, see some additional suggestions and commentary at install gcc 4.6.1 on OS X 10.11 .
For what it's worth, MacPorts has ports for all recent versions that should be sufficiently easy for everyone (who knows how to code!) to read who doesn't want to install MacPorts but prefers to install the various dependencies mentioned here some other way.
A slightly tweaked personal version of the port for gcc 6.3.0:
https://github.com/RJVB/macstrop/blob/master/lang/gcc6/Portfile
The reason I mention that one (and post this answer) is that this tweaked version shows how to get G++ to use libc++ instead of libstdc++. That's a prerogative for being able to use G++ as a real replacement for clang++ that can be used without worrying about C++ runtime incompatibilities. This patch has allowed me to use g++ to build KDE (KF5) code and run it against Qt5 and the KF5 frameworks built with various clang compiler versions. (The patch files are in .../gcc6/files .)
Some explanation that might help interpreting the Tcl code of the linked file:
Ignore anything that's specific to $subport == "libgcc".
As you can see, you need gmp, mpc, mpfr and isl (the other dependencies should be of no interest if you're installing on your own).
The configure.args expressions construct the argument list to the configure script, configure.env and build.env add environmental variables for the configure and build (make) commands. Many of the configure options here are to ensure that the build uses dependencies from MacPorts but they'd probably be required too if you want or have to use a location not controlled by SIP and that isn't included in standard PATH definitions (the compiler still ought to work when invoked through a process that resets the path).
The configure and build are done in a build directory that sits next to the source directory, which makes it very easy to start over or just clean up without throwing away the sources.
After the configure step the build is done with "make bootstrap-lean" - which still creates about 1.7Gb of data in that build directory.

Resources