I am running gdb like this:
x-compiler-gdb path/to/u-boot
Where "x-compiler" is just whatever cross compiler suffix I am using and /path/to
is the path where my u-boot file lives.
Then in GDB I do something like:
(gdb) target extended-remote :3333
Remote debugging using :3333
(gdb) p/x (*(struct global_data*)$r9)->relocaddr
$1 = 0x27f7a000
This is cool because it stores the relocation address in a variable called $1
(gdb) symbol-file
Discard symbol table from `/home/...../u-boot'? (y or n) y
No symbol file now.
(gdb) add-symbol-file u-boot $1 <------------- HERE
add symbol table from file "u-boot" at
.text_addr = 0x12345678
(y or n) y
Reading symbols from u-boot...
(gdb)
I was able to use variable $1
to use the relocation address. But next I want to reload the original filename that I passed in because I want to script this up and make it more generic.
I don't know how to pass in variables to gdb like gdb <binary> U_BOOT_FILE=/path/to/binary/u-boot
so that I can use that inside the gdb environment.
Or better still, I don't know how to print / store the name of the symbol (binary) file that I have passed in so that I can reference it later.
set confirm off
target extended-remote <remote_ip>:3333 <----- pass in the remote IP address
p/x (*(struct global_data*)$x18)->relocaddr
symbol-file
add-symbol-file u-boot-v2020.04+git999/u-boot $1 <---- Hardcoded symbol filename
You can see I have to hard-code the file name u-boot-v2020.04+git999/u-boot
which could be a different version or path.
Ideally I would store that into $2
or such - but I can't see how this is done. Any reference to "gdb variable storage" or such just references program variables from the binary.
Also I would like to pass in the remote IP address perhaps as $3
Note: this is to debug yocto/bitbake gcc built u-boot.
I'd use the Python API to create a new command. Place the following into a Python file, e.g. /tmp/gdb-command.py
:
class ConnectAndRelocateCommand (gdb.Command):
"""
Usage: connect-and-relocate IP
Connect to IP:3333, establish the relocation address and reload
the current symbol-file at that address.
"""
def __init__ (self):
gdb.Command.__init__ (self, "connect-and-relocate", gdb.COMMAND_NONE)
def invoke(self, args, from_tty):
# 1. Grab the IP address from the arguments.
argv = gdb.string_to_argv(args)
if len(argv) != 1:
raise gdb.GdbError("usage: connect-and-relocate IP")
ip = argv[0]
# 2. Connect to the remote server.
gdb.execute(f"target extended-remote {ip}:3333")
# 3. Find filename of current symfile.
pspace = gdb.selected_inferior().progspace
symbol_file = pspace.symbol_file
if symbol_file is None:
raise gdb.GdbError("no symbol file loaded")
filename = symbol_file.filename
# 4. Find relocation address.
reloc_addr = gdb.parse_and_eval("(*(struct global_data*)$r9)->relocaddr")
# 5. Remove symbol file.
gdb.execute("symbol-file")
# 6. Reload symbol file at relocation address.
reload_cmd = f"add-symbol-file {filename} {reloc_addr}"
gdb.execute(reload_cmd)
print("relocation complete")
ConnectAndRelocateCommand ()
print("Command script loaded OK")
Then in a GDB session just source /tmp/gdb-command.py
.
Assuming that loading the script worked without errors you should see the Command script loaded OK
message. Your GDB session now has the command connect-and-relocate
available. Use help connect-and-relocate
for more details.
With luck this should do what you want. If you have some basic Python knowledge you should be able to tweak the script to meet your needs.
The GDB Python API docs can be found here.