由于比较简单,就不需要解释了吧,看注释应该足够了
最后打印出来的possible entry为函数调用的入口
由于仅仅是一个demo,就不要要求太精确了,主要还是为了演示ppc的堆栈结构
符号可以通过多lookup_symbol()解析(需要自己实现,查询相关ELF文件字段)
/**
* ppc stack back trace simple demo
* for 32bit ppc only (gnu-linux)
* compile with -O0
*/
/*
run-time stack layout
| ... |
| LR saved |
+---------------+
| Back chain |
| reserved |
| GPR saved |
| locals |
| dyn alloc |
| param(callee) |
| LR saved |
+---------------+
| Back Chain |
| ... |
*/
#include <stdio.h>
/**
* dummy entry finding routine
*/
unsigned long find_entry(unsigned long current)
{
unsigned long p = current;
unsigned long entry;
unsigned long ret = 0;
if(current == 0)
return 0;
while(1) {
p -= 4;
entry = *(unsigned long*)p;
/* b but not bl */
if((entry & 0x48000001 == 0x48000000)) {
break;
} else if (entry == 0x4e800020) { /* blr */
break;
} else if ((entry & 0x94210000) == 0x94210000) { /* stwu */
ret = p;
break;
}
}
return ret;
}
int foo(void)
{
unsigned long r1, lr, p;
char buf[24]; /* consume more stack */
/* get the current stack pointer */
__asm__ __volatile__ ("mr %0, 1\n\t": "=r"(r1));
/* don't work for self-modify code, though */
lr = (unsigned long)&foo + 32; /* assume foo >32 bytes */
p = lr;
while(1) {
unsigned long entry = *(unsigned long*)p;
/* don't care with stwux */
if( (entry & 0x94210000) == 0x94210000) { /* stwu */
long off;
off = entry & 0xFFFF;
if(off & 0x8000) {
off |= ((0xFFFF) << 16); /* signed extend */
}
printf("off: %d\n", off);
/* unsigned arith: find stack entry */
r1 += (-off);
break;
}
p -= 4;
}
while(r1) {
lr = *(unsigned long*)(r1+4);
printf("stack dump: 0x%lx\n", r1);
printf("lr dump: 0x%lx\n", lr);
/* this is the call stack entry function
* please verify with objdump
*/
printf("possible entry: 0x%lx\n", find_entry(lr));
r1 = *(unsigned long*)r1; /* previous stack frame */
}
return 0;
}
/* create more function calls for back trace testing */
void bar(int p)
{
foo();
}
void baz(void)
{
bar(0);
}
int main(int argc, char* argv[])
{
baz();
return 0;
}
|
阅读(1719) | 评论(0) | 转发(0) |