do_page_fault() #2: sending SIGSEGV to linux_stb for invalid read access from
00000000 (epc == 00000000, ra == 00000000)
因为缺少正确的$ra,linux gdb也无法显示调用栈。
可能的原因很多,比如该线程的内核栈被冲掉(可能性较少,因为内核栈应用层改不到)。
或者,该用户线程执行时把栈给冲掉了导致$ra为0,所以跳到0去执行,导致epc为零。

应对方法:
希望栈没有被冲太多:0)
到do_page_fault()的地方,取得sp(r29)的值,然后显示该用户栈信息。

        printk("stack pointer: 0x%lx\n", regs->regs[29]);
        {
            int i;
            unsigned long * stack;

            stack = (unsigned long *)regs->regs[29];
            for(i = 0; i < 64; i ++)
            {
                if(i % 4 == 0) printk("\n");
                printk("%08lx ", stack[i]);
            }
            printk("\n");
           
        }

比如:
00000000 00000000 00208000 004f3288
00799c60 004f330c 00000000 30590e44
30590df4 008b3918 008b3af0 004de850
00000000 30590e44 00001437 0020e0ff
00799c60 00000000 00000001 004eb8fc
00000000 00000000 00000000 00000000
00799c60 00000000 00000001 00000000

其中004xxxxx 005xxxxx ... 依赖于程序代码段大小,多数是栈中保留的函数返回地址。
然后objdump -DS app.out
不难找到一些棕丝马迹。