I'd like to do backtrace on MIPS. Then, I face one problem: how do I get the current PC register value, since it doesn't belong to 32 normal registers.. Thanks for your suggestion..
-
Can you call a dummy function that reads it off the stack? I don't know MIPS, but just an idea. – FatalError Mar 11 '13 at 04:07
3 Answers
Make a subroutine that looks somewhat like:
.text
.globl GetIP
GetIP:
move $v0, $ra
jr $ra
And then call the routine; it'll give you the address of the first instruction after the call.
- 2,975
- 19
- 26
after a jal call it will be copied to the ra register... so you could store ra, then jal to the next line, read ra, restore ra.
- 14,399
- 2
- 48
- 76
Although this question isn't tagged c, I figured it might be useful to share a solution utilizing inline assembly in gcc.
__attribute__((noinline)) static void *get_pc(void)
{
void *pc;
asm volatile ("move %0, $ra" : "=r"(pc));
return pc;
}
Of course, the gist of the solution is the same as the currently accepted answer. Since the function is very small, it is a good candidate for inlining when optimization is turned on. However, if that function were inlined, its return value would be invalid : it would simply return some value of ra in the calling function, since a jal or jalr wouldn't be generated, and ra thus not set to the instruction following jal/jalr. This is why __attribute__((noinline)) is essential in this case.
- 18,476
- 5
- 50
- 64
-
A more portable way would be to use GCC's builtins to retrieve the return address: `__builtin_extract_return_addr (__builtin_return_address (0))` instead of the inline assembly. – stefanct Dec 22 '22 at 20:34