2

Is there any way to call a function on a remote target that's attached via JTAG? Currently I have OpenOCD hooked up to a target and I'm attached with gdb, and I know the address of the function I want to call as well as its signature.

With a normal binary and gdb, the following (somewhat surprisingly) works. Supposing I have a function like:

static int f(int x) {
    printf("The value of x is %d\n", x);
    return x*2;
}

I can run that function, even in a stripped binary, under gdb, as long as I know its address:

cosimo:~ moyix$ gdb -q --args ./hello 
Reading symbols from ./hello...(no debugging symbols found)...done.
(gdb) break *0x100000ee0
Breakpoint 1 at 0x100000ee0
(gdb) r
Starting program: /Users/moyix/hello 

Breakpoint 1, 0x0000000100000ee0 in _mh_execute_header ()
(gdb) call (0x100000f20)(10)
The value of x is 10
$1 = 20

But trying to do something similar with gdb hooked up to OpenOCD gives me:

moyix@dev:~/git/openocd-code$ arm-none-eabi-gdb -q
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
0x8006b06c in ?? ()
(gdb) call (0xC0066E08)(0x10000, 4, 0, 0, 0)
Entry point address is not known.
(gdb) 

I gather from a bit of googling that it's because gdb wants somewhere to place its dummy stack frame, and since it has no symbol information or even an entry point for the binary it doesn't know where to put it. Is there any way to manually give it a location for its dummy frame (with the hope that it'll put things back the way they were once the function executes...)?

1

This isn't the cleanest solution, and I still don't know how to make gdb do it properly. My solution was to simply manually "call" the function by:

  1. Save the current set of registers (info reg => log file).
  2. Set up parameters by manually modifying registers, pushing things onto the stack, etc, being careful to make sure not to overwrite anything higher than the current stack pointer.
  3. Put a breakpoint on each return from the function I want to call. (Note: possibly in the future it would work better to just set the return address to some arbitrary point and then set a breakpoint on that point.)
  4. Set the program counter to the address of the function I want to call.
  5. Once the breakpoint hits, inspect return values etc.
  6. Restore the register values by hand (including the stack pointer).

This isn't perfect, since it requires a lot of manual effort at the beginning and end, but works well enough for occasional use.

0

I have come across this question for the same issue on a different use case: debugging an ELF binary through qemu-arm, trying to call code from the attached process.

I could give gdb the information it missed, designating the target binary file as a symbol file (using the symbol-file command).

https://sourceware.org/gdb/onlinedocs/gdb/Files.html

Of course, it might be more complicated in your case. Linking a binary file using the live in-device addresses might do the trick, although it may not be trivial.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.