summaryrefslogtreecommitdiff
path: root/libcpu/aarch64/common/backtrace.c
blob: c3e3803f9306fab540893e8fddffe719e9ad32cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-06-02     Jesven       the first version
 */

#include <rtthread.h>
#include <backtrace.h>

#define BT_NESTING_MAX 100

static int unwind_frame(struct bt_frame *frame)
{
    unsigned long fp = frame->fp;

    if ((fp & 0x7)
#ifdef RT_USING_LWP
         || fp < KERNEL_VADDR_START
#endif
            )
    {
        return 1;
    }
    frame->fp = *(unsigned long *)fp;
    frame->pc = *(unsigned long *)(fp + 8);
    return 0;
}

static void walk_unwind(unsigned long pc, unsigned long fp)
{
    struct bt_frame frame;
    unsigned long lr = pc;
    int nesting = 0;

    frame.fp = fp;
    while (nesting < BT_NESTING_MAX)
    {
        rt_kprintf(" %p", (void *)lr);
        if (unwind_frame(&frame))
        {
            break;
        }
        lr = frame.pc;
        nesting++;
    }
}

void backtrace(unsigned long pc, unsigned long lr, unsigned long fp)
{
    rt_kprintf("please use: addr2line -e rtthread.elf -a -f %p", (void *)pc);
    walk_unwind(lr, fp);
    rt_kprintf("\n");
}