toolchain: add gdb wrapper that automatically passes the gdbinit file
PATCH v2 1/1 toolchain: add gdb wrapper that automatically passes the gdbinit file
From: Thomas De Schampheleire <[email protected]>
Buildroot already provided a gdbinit file to set the right sysroot, but required users to pass this file explicitly when invoking gdb.
Make the process a bit more user-friendly by creating a gdb wrapper that passes the gdbinit file to the real gdb program.
The code needs to take into account several cases (internal toolchain, external toolchain, ...) because the name and type of the real gdb program differs.
The documentation is updated to reflect this change.
---
v2:
- use "$@" instead of $@ in shell wrapper
- update release in manual to match 2016.05
docs/manual/using-buildroot-debugger.txt | 7 +++-- package/gdb/gdb.mk | 2 +- toolchain/helpers.mk | 36 +++++++++++++++++++--- toolchain/toolchain-external/toolchain-external.mk | 10 +++--- 4 files changed, 42 insertions(+), 13 deletions(-)
docs/manual/using-buildroot-debugger.txt +4 -3
@@ -35,7 +35,7 @@ Then, on the host, you should start the cross gdb using the following command line: ---------------------------- -<buildroot>/output/host/usr/bin/<tuple>-gdb -x <buildroot>/output/staging/usr/share/buildroot/gdbinit foo +<buildroot>/output/host/usr/bin/<tuple>-gdb foo ---------------------------- Of course, +foo+ must be available in the current directory, built
@@ -43,8 +43,9 @@ with debugging symbols. Typically you start this command from the directory where +foo+ is built (and not from +output/target/+ as the binaries in that directory are stripped). -The +<buildroot>/output/staging/usr/share/buildroot/gdbinit+ file will tell the -cross gdb where to find the libraries of the target. +Since Buildroot 2016.05, the above gdb program is actually a wrapper script +that passes a gdbinit file. The gdbinit file tells the cross gdb where to find +the libraries of the target. Finally, to connect to the target from the cross gdb:
package/gdb/gdb.mk +1 -1
@@ -187,7 +187,7 @@ endef HOST_GDB_POST_INSTALL_HOOKS += HOST_GDB_ADD_SYMLINK -HOST_GDB_POST_INSTALL_HOOKS += gen_gdbinit_file +HOST_GDB_POST_INSTALL_HOOKS += setup_gdb_wrapper $(eval $(autotools-package)) $(eval $(host-autotools-package))
toolchain/helpers.mk +32 -4
@@ -387,8 +387,36 @@ check_unusable_toolchain = \ fi # -# Generate gdbinit file for use with Buildroot -# -gen_gdbinit_file = \ +# Create a gdb wrapper that sources a minimal gdbinit file. We don't need to +# create a gdbtui wrapper because that one actually calls gdb. +# For internal toolchains: +# - if BR2_PACKAGE_HOST_GDB is set, gdb is built by buildroot and a real file at +# $(TARGET_CROSS)gdb ( == $(HOST_DIR)/usr/bin/$(GNU_TARGET_NAME)-gdb ) +# For external toolchains: +# - if BR2_PACKAGE_HOST_GDB is not set, gdb is provided by the external +# toolchain and $(TARGET_CROSS)gdb is a symlink. +# - if BR2_PACKAGE_HOST_GDB is set, gdb is built by buildroot and a real file at +# $(HOST_DIR)/usr/bin/$(GNU_TARGET_NAME)-gdb +# +define setup_gdb_wrapper mkdir -p $(STAGING_DIR)/usr/share/buildroot/ ; \ - echo "set sysroot $(STAGING_DIR)" > $(STAGING_DIR)/usr/share/buildroot/gdbinit + echo "set sysroot $(STAGING_DIR)" > $(STAGING_DIR)/usr/share/buildroot/gdbinit ; \ + if [ -f $(TARGET_CROSS)gdb -a ! -e $(TARGET_CROSS)gdb.real ]; then \ + gdb_wrapper=$(TARGET_CROSS)gdb ; \ + real_gdb=$${gdb_wrapper}.real ; \ + mv $${gdb_wrapper} $${real_gdb} ; \ + elif [ -L $(TARGET_CROSS)gdb ]; then \ + gdb_wrapper=$(TARGET_CROSS)gdb ; \ + real_gdb=`readlink -f $(TARGET_CROSS)gdb`; \ + rm $(TARGET_CROSS)gdb ; \ + elif [ -f $(HOST_DIR)/usr/bin/$(GNU_TARGET_NAME)-gdb ]; then \ + gdb_wrapper=$(HOST_DIR)/usr/bin/$(GNU_TARGET_NAME)-gdb ; \ + real_gdb=$${gdb_wrapper}.real ; \ + mv $${gdb_wrapper} $${real_gdb} ; \ + fi ; \ + if [ -n "$${gdb_wrapper}" ]; then \ + echo "#!/bin/sh" > $${gdb_wrapper} ; \ + echo "$${real_gdb} -x $(STAGING_DIR)/usr/share/buildroot/gdbinit \"\$$@\"" >> $${gdb_wrapper} ; \ + chmod +x $${gdb_wrapper} ; \ + fi +endef
toolchain/toolchain-external/toolchain-external.mk +5 -5
@@ -741,12 +741,12 @@ define TOOLCHAIN_EXTERNAL_INSTALL_WRAPPER endef # -# Generate gdbinit file for use with Buildroot +# Generate gdb wrapper and gdbinit file for use with Buildroot # -define TOOLCHAIN_EXTERNAL_INSTALL_GDBINIT +define TOOLCHAIN_EXTERNAL_INSTALL_GDB_WRAPPER $(Q)if test -f $(TARGET_CROSS)gdb ; then \ - $(call MESSAGE,"Installing gdbinit"); \ - $(gen_gdbinit_file); \ + $(call MESSAGE,"Creating gdb wrapper and gdbinit file"); \ + $(setup_gdb_wrapper); \ fi endef
@@ -771,7 +771,7 @@ define TOOLCHAIN_EXTERNAL_INSTALL_STAGING_CMDS $(TOOLCHAIN_EXTERNAL_INSTALL_SYSROOT_LIBS) $(TOOLCHAIN_EXTERNAL_INSTALL_SYSROOT_LIBS_BFIN_FDPIC) $(TOOLCHAIN_EXTERNAL_INSTALL_WRAPPER) - $(TOOLCHAIN_EXTERNAL_INSTALL_GDBINIT) + $(TOOLCHAIN_EXTERNAL_INSTALL_GDB_WRAPPER) endef # Even though we're installing things in both the staging, the host
Signature · 1 line
2.7.3
PATCH v2 1/1 toolchain: add gdb wrapper that automatically passes the gdbinit file
Thomas, All,
On 2016-04-29 20:03 +0200, Thomas De Schampheleire spake thusly:
Quoted 8 lines
From: Thomas De Schampheleire <[email protected]>
Buildroot already provided a gdbinit file to set the right sysroot, but required users to pass this file explicitly when invoking gdb.
Make the process a bit more user-friendly by creating a gdb wrapper that passes the gdbinit file to the real gdb program.
Quoted 8 lines
The code needs to take into account several cases (internal toolchain, external toolchain, ...) because the name and type of the real gdb program differs.
The documentation is updated to reflect this change.
Signed-off-by Thomas De Schampheleire <[email protected]>---
[--SNIP--]
Quoted 16 lines
toolchain/helpers.mk +5
-3@@ -387,8 +387,36 @@ check_unusable_toolchain = \ fi # -# Generate gdbinit file for use with Buildroot -# -gen_gdbinit_file = \ +# Create a gdb wrapper that sources a minimal gdbinit file. We don't need to +# create a gdbtui wrapper because that one actually calls gdb. +# For internal toolchains: +# - if BR2_PACKAGE_HOST_GDB is set, gdb is built by buildroot and a real file at +# $(TARGET_CROSS)gdb ( == $(HOST_DIR)/usr/bin/$(GNU_TARGET_NAME)-gdb )
toolchain/helpers.mk check_unusable_toolchain = \ · line 403
Quoted 10 lines
toolchain/helpers.mk +8
-1+# For external toolchains: +# - if BR2_PACKAGE_HOST_GDB is not set, gdb is provided by the external +# toolchain and $(TARGET_CROSS)gdb is a symlink. +# - if BR2_PACKAGE_HOST_GDB is set, gdb is built by buildroot and a real file at +# $(HOST_DIR)/usr/bin/$(GNU_TARGET_NAME)-gdb +# +define setup_gdb_wrapper mkdir -p $(STAGING_DIR)/usr/share/buildroot/ ; \ - echo "set sysroot $(STAGING_DIR)" > $(STAGING_DIR)/usr/share/buildroot/gdbinit + echo "set sysroot $(STAGING_DIR)" > $(STAGING_DIR)/usr/share/buildroot/gdbinit ; \
You don't need a continuation line here.
toolchain/helpers.mk check_unusable_toolchain = \ · line 416
Quoted 13 lines
toolchain/helpers.mk +13
-0+ if [ -f $(TARGET_CROSS)gdb -a ! -e $(TARGET_CROSS)gdb.real ]; then \ + gdb_wrapper=$(TARGET_CROSS)gdb ; \ + real_gdb=$${gdb_wrapper}.real ; \ + mv $${gdb_wrapper} $${real_gdb} ; \ + elif [ -L $(TARGET_CROSS)gdb ]; then \ + gdb_wrapper=$(TARGET_CROSS)gdb ; \ + real_gdb=`readlink -f $(TARGET_CROSS)gdb`; \ + rm $(TARGET_CROSS)gdb ; \ + elif [ -f $(HOST_DIR)/usr/bin/$(GNU_TARGET_NAME)-gdb ]; then \ + gdb_wrapper=$(HOST_DIR)/usr/bin/$(GNU_TARGET_NAME)-gdb ; \ + real_gdb=$${gdb_wrapper}.real ; \ + mv $${gdb_wrapper} $${real_gdb} ; \ + fi ; \
I was surprised to see that we did not already have code to locate the cross-gdb, especially for external toolchains...
I could not find where we copy gcc et al. either... :-/
toolchain/helpers.mk check_unusable_toolchain = \ · line 419
Quoted 3 lines
toolchain/helpers.mk +3
-0+ if [ -n "$${gdb_wrapper}" ]; then \ + echo "#!/bin/sh" > $${gdb_wrapper} ; \ + echo "$${real_gdb} -x $(STAGING_DIR)/usr/share/buildroot/gdbinit \"\$$@\"" >> $${gdb_wrapper} ; \
Please do not introduce another hard-coded abslute path. You should derive the path to the gdbinit file relative to the gdb executable, if at all possible.
Regards,
Yann E. MORIN.
Signature · 6 lines
.-----------------.--------------------.------------------.--------------------. | Yann E. MORIN | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: | | +33 662 376 056 | Software Designer | \ / CAMPAIGN | ___ | | +33 223 225 172 `------------.-------: X AGAINST | \e/ There is no | | http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL | v conspiracy. | '------------------------------^-------^------------------^--------------------'
PATCH v2 1/1 toolchain: add gdb wrapper that automatically passes the gdbinit file
In reply to Thomas De SchampheleireHello,
Quoted 12 lines · Thomas De Schampheleire
From: Thomas De Schampheleire <[email protected]>
Buildroot already provided a gdbinit file to set the right sysroot, but required users to pass this file explicitly when invoking gdb.
Make the process a bit more user-friendly by creating a gdb wrapper that passes the gdbinit file to the real gdb program.
The code needs to take into account several cases (internal toolchain, external toolchain, ...) because the name and type of the real gdb program differs.
Quoted 7 lines
The documentation is updated to reflect this change.
Signed-off-by Thomas De Schampheleire <[email protected]>---
v2:
- use "$@" instead of $@ in shell wrapper
- update release in manual to match 2016.05
After discussing at the Buildroot meeting, we decided to reject this patch. Indeed, we believe this additional wrapper is not really needed, and hides some more magic which we prefer to keep visible to the user.
What we could do is to make it a bit easier for users to find the gdbinit file by having a "staging" symlink pointing to the sysroot, installed in the host directory. This way, even if your toolchain is installed in /opt/br-baz/, you can do:
/opt/br-baz/usr/bin/<blah>-gdb -x /opt/br-baz/usr/staging/usr/share/buildroot/gdbinit
Best regards,
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com