Helge,
+unsigned long return_address(unsigned int level) +{ + struct unwind_frame_info info; + struct pt_regs r; + unsigned long sp; + + /* initialize unwind info */ + asm volatile ("copy %%r30, %0" : "=r"(sp)); + memset(&r, 0, sizeof(struct pt_regs)); + r.iaoq[0] = (unsigned long) current_text_addr(); + r.gr[2] = (unsigned long) __builtin_return_address(0); + r.gr[30] = sp; + unwind_frame_init(&info, current, &r); + + /* unwind stack */ + ++level; + do { + if (unwind_once(&info) < 0 || info.ip == 0) + return 0; + if (!__kernel_text_address(info.ip)) { + return 0; + } + } while (info.ip && level--); + + return info.ip; +} +
Can you show an objdump of this function once it is compiled? I suspect the stack pointer initialization here is not reliable.
Ideally unwind_frame_init is called with the frame address in gr[30]. With a big struct like pt_regs on the stack, the sp initialization might be quite far from the actual frame address.
The unwind_once() code uses like heuristics to try to recover from inaccurate stack pointers (by aligning and stepping the frame 64 bytes at a time) but that is really a brute force guess.
I realize I used a similar construct in traps.c, but even there I think it doesn't work reliably.
Maybe somebody else on the list (Dave? :) can suggest a better way to do this.
randolph -- To unsubscribe from this list: send the line "unsubscribe linux-parisc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html