Building GDB and GDBserver for cross debugging
1. Problem statement
"I have a ARM GNU/Linux board, and I want to be able to debug programs running in it, from the comfort of my x86_64 GNU/Linux machine. How do I build GDB and GDBserver for this scenario? I'm confused with the configure options I need to specify. Do I need to cross compile GDB for ARM too? Help!"
2. build, host, target, what??
As most GNU programs, GDB uses autoconf as part of its build system.
Here's the chapter of the GNU autoconf, automake and libtool book everyone building cross tools should read (do follow the right arrows):
Specifically, understanding the distinction between build, host and target is crucial.
Autotools Mythbuster has a nice explanation. Simplified:
When using autoconf, there are three system definitions (or machine definitions) that are used to identify the “actors” in the build process; (...) These three definitions are: host The system that is going to run the software once it is built. Once the software has been built, it will execute on this particular system. build The system where the build process is being executed. For most uses this would be the same as the host system, but in case of cross-compilation the two obviously differ. target The system against which the software being built will run on. This only exists, or rather has a meaning, when the software being built may interact specifically with a system that differs from the one it's being executed on (our host). This is the case for compilers, debuggers, profilers and analyzers and other tools in general.
Go on read those linked chapters please; I'll wait. Alright, onwards.
When thinking in terms of "parked in front of a x86_64 machine", we say GDB runs on your host system, the x86_64 GNU/Linux machine, while GDBserver runs on the target, the ARM GNU/Linux board/machine.
However, GDB and GDBserver are separate programs. They get built separately, so we get to apply the build/host/target distinction for each separate build step.
3. Okay, how does that apply to GDB and GDBserver then?
3.1. For GDB
You need a GDB that runs on x86. With autoconf/configure, you use --host to specify where the program runs. So in your case that would be --host=x86_64-unknown-linux-gnu. However, if the program is meant to be run on the same system you are building from, then you don't need to specify that, as configure will pick your system as default for --host automatically. What you need is to make it so that the built GDB understands how to debug ARM GNU/Linux programs. This is where --target comes along. Say you have a arm-linux-gnueabi-gcc etc. cross toolchain available on your x86_64 development host, used for building programs that run on your ARM board (file names might vary, even for ARM GNU/Linux). From the compiler's file name, or from running arm-linux-gnueabi-gcc -v (look for the "Target:" line in the output), we see that gcc was configured with --target=arm-linux-gnueabi. We pass the same --target switch to GDB's configure. Done. That's it, really.
You'll see something like this:
$ /path/to/gdb-src/configure --target=arm-linux-gnueabi checking build system type... x86_64-unknown-linux-gnu checking host system type... x86_64-unknown-linux-gnu checking target system type... arm-unknown-linux-gnueabi
If you don't specify --target, then the configure script defaults the target system to the same system you're building on. In this case, that would be x86_64-unknown-linux-gnu, which is not what we want.
3.2. For GDBserver
So again, GDBserver runs on the "target" machine, the ARM GNU/Linux one. You could copy the sources over the the ARM GNU/Linux machine, and build it there. The standard /path/to/gdb/gdbserver/configure && make && make install will work fine.
However, you want to build GDBserver in the comfort of your x86_64 GNU/Linux host. You have an ARM cross compiler handy after all, right? Recapping from autoconf's build/host/target distinction, --host is used to specify where the program runs. Bingo! Since GDBserver will run on ARM, you pass --host=arm-linux-gnueabi to GDBserver's configure. You'll get something like:
$ /path/to/gdb-src/gdb/gdbserver/configure --host=arm-linux-gnueabi checking build system type... x86_64-unknown-linux-gnu checking host system type... arm-unknown-linux-gnueabi checking target system type... arm-unknown-linux-gnueabi
("But why not --target?" Okay, you need to go read the build/host/target distinction again. --target doesn't really make sense for GDBserver, because it not a "cross" tool -- it knows how to debug the programs on its own system. It's no different from most other programs running on the ARM system, like grep, sed, etc, so you cross build it just like all other autoconf/configure programs.)
4.1. make uses system compiler?
If you've configured with --host=$host, but make uses the system's gcc instead of $host-gcc, make sure the latter can be found in your PATH, and that you can execute it (e.g., try $ arm-unknown-linux-gnueabi-gcc -v), and start over. The reason is that if configure doesn't find a usable $host-gcc, then it falls back to "gcc". See here for more info.
5. On separate build dirs
Final note: You don't have to, but I recommend building on a separate build directory from the sources. Like,
Sources in gdb/src/
Build directory for gdb in gdb/build-gdb/
Build directory for gdbserver in gdb/build-gdbserver/
Cd into gdb/build-gdb/, and do '../src/configure ...'
Cd into gdb/build-gdbserver/, and do '../src/gdb/gdbserver/configure ...'
This way, at any time you want to do a build from scratch, you just need to wipe (rm -rf) the build directories.
It's not that long! Learning this stuff properly will translate into cross building all sorts of GNU autoconf based programs and libraries, so it's a skill worth having.
Anyway, to recap:
For GDB, do 'configure --target=arm-linux-gnueabi'. Run the toplevel configure for that (/path/to/gdb-src/configure).
For GDBserver do 'configure --host=arm-linux-gnueabi'. Run GDBserver's configure for that (/path/to/gdb-src/gdb/gdbserver/configure).