Skip to content

Instantly share code, notes, and snippets.

@ArtemPisarenko
Created October 3, 2018 14:12
Show Gist options
  • Save ArtemPisarenko/6d54d14db0509d02d60be3a3a750b559 to your computer and use it in GitHub Desktop.
Save ArtemPisarenko/6d54d14db0509d02d60be3a3a750b559 to your computer and use it in GitHub Desktop.
GDB script to workaround issues with GDB debugging in Qt Creator
#!/usr/bin/python
#
# GDB python script for silly QtCreator, when it used to run debug sessions
# with attaching to running process or remote gdb server.
#
# It automatically fixes following issues:
# - there are no way to allow automatic loading of .gdbinit/python scripts supplied with binary
# in a safe and/or convinient manner, i.e. without disabling safe-load option and/or
# playing with safe-load paths in ~/.gdbinit
# (you may see warning from gdb in debugger console)
# - execution automatically continued after connecting to remote gdb target,
# as a result you can't do some early preparations
# (e.g. insert breakpoints in everyting that runs before 'main')
# - other resctrictions because of cwd leaves default (user home)
#
# Using:
# Just add 'source /path/to/this_script' to "Additional Startup Commands"
# in "Options..."->"Debugger"->"GDB" tab.
# When attaching to process, if directory with binary contains file named '<binary_name>.debugpath',
# then its content being read as full path and if it's valid, then it set as current working directory.
# Setting cwd also implies loading scripts from it rather than from binary location, which adds support of '.gdbinit' also.
#
# Reqirements for attach to gdb target:
# 'readelf' must be installed
#
# TODO: respect auto-load parameter (it may be off)
import gdb
import os.path
import subprocess
log_prefix = __file__ + ": "
def add_program_to_autoloadsafepath(exec_binary_path):
gdb.execute("add-auto-load-safe-path " + os.path.dirname(exec_binary_path))
def load_program_scripts(exec_binary_path):
global log_prefix
absdirpath = os.path.dirname(exec_binary_path) + "/"
reldirpath = absdirpath
if (os.path.isfile(exec_binary_path + ".debugpath")):
with open(exec_binary_path + ".debugpath", 'r') as f_debugpath:
debugpath = f_debugpath.read().replace('\n', '')
if (os.path.isdir(debugpath)):
gdb.write(log_prefix + " auto changing cwd to '" + debugpath + "'\n")
gdb.execute("cd " + debugpath)
absdirpath = debugpath + "/"
reldirpath = ""
if (os.path.isfile(absdirpath + ".gdbinit")):
gdb.write(log_prefix + " auto loading '.gdbinit'\n")
gdb.execute("source .gdbinit")
debug_bin_path = absdirpath + os.path.basename(exec_binary_path)
script_path = reldirpath + os.path.basename(exec_binary_path)
if (os.path.isfile(debug_bin_path + "-gdb.gdb")):
script_path += "-gdb.gdb"
elif (os.path.isfile(debug_bin_path + "-gdb.py")):
script_path += "-gdb.py"
elif (os.path.isfile(debug_bin_path + "-gdb.scm")):
script_path += "-gdb.scm"
else:
return
gdb.write(log_prefix + " auto loading '" + script_path + "'\n")
gdb.execute("source " + script_path)
def set_pause_on_entry(exec_binary_path):
entry_point_address = subprocess.check_output('readelf -h ' + exec_binary_path + ' | sed -n \'s/\ *Entry point.*\:\ *//p\' | tr -d \'\n\'', shell=True).decode()
gdb.Breakpoint("*"+entry_point_address, internal=True)
def event_handler_new_objfile(event):
global log_prefix
# Assuming this event fired only for executable binary,
# which expected to be loaded first.
# Disable event for other object files, which may potentially be loaded later
gdb.events.new_objfile.disconnect(event_handler_new_objfile)
exec_binary_path = event.new_objfile.filename
add_program_to_autoloadsafepath(exec_binary_path)
if (gdb.selected_inferior().was_attached):
# Attaching to running process:
# Here it's too late to fix-up auto-loading scripts,
# because by default cwd is user home.
# So let's just emulate necessary steps ourselves, but with differences
load_program_scripts(exec_binary_path)
else:
# Attaching to remote gdb target:
# Don't let program start execution
set_pause_on_entry(exec_binary_path)
gdb.write(log_prefix + " loaded\n")
gdb.events.new_objfile.connect(event_handler_new_objfile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment