Chinaunix首页 | 论坛 | 博客
  • 博客访问: 175344
  • 博文数量: 42
  • 博客积分: 2185
  • 博客等级: 大尉
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-11 21:32
文章分类

全部博文(42)

文章存档

2012年(5)

2011年(13)

2010年(6)

2009年(18)

我的朋友

分类: LINUX

2009-06-16 18:04:17

由于比较简单,就不需要解释了吧,看注释应该足够了
最后打印出来的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;
}

阅读(1685) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~