├── README.md ├── Makefile ├── arm-backtrace.h ├── test.cc └── arm-backtrace.c /README.md: -------------------------------------------------------------------------------- 1 | arm平台下实现函数调用回溯,以便于程序错误时进行回溯 2 | 编译的时候必须加上-fno-omit-frame-pointer -mapcs选项 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | arm-hisiv100nptl-linux-gcc -c arm-backtrace.c -fno-omit-frame-pointer -mapcs -rdynamic -Wall 3 | arm-hisiv100nptl-linux-ar rs libarm-backtrace.a *.o 4 | arm-hisiv100nptl-linux-g++ test.cc -fno-omit-frame-pointer -mapcs -rdynamic -Wall -L./ -larm-backtrace -ldl -o test 5 | 6 | .PHONY:clean 7 | clean: 8 | rm -rf *.o *.a test 9 | -------------------------------------------------------------------------------- /arm-backtrace.h: -------------------------------------------------------------------------------- 1 | /******************************************** 2 | * 3 | * @file arm-backtrace.c 4 | * @author wuwc.zeno@inesa-e.com 5 | * @changelog: 6 | * 2014/06/24 create the file 7 | * 8 | * 9 | *******************************************/ 10 | 11 | #ifndef ARM_BACKTRACE_H__ 12 | #define ARM_BACKTRACE_H__ 13 | 14 | #ifdef __cplusplus 15 | extern "C" 16 | { 17 | #endif // __cplusplus 18 | 19 | int backtrace_arm(void **array, int size); 20 | char ** backtrace_symbols_arm(void *const *array, int size); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif // __cplusplus 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /test.cc: -------------------------------------------------------------------------------- 1 | /******************************************** 2 | * 3 | * @file arm-backtrace.c 4 | * @author wuwc.zeno@inesa-e.com 5 | * @changelog: 6 | * 2014/06/24 create the file 7 | * 8 | * 9 | *******************************************/ 10 | 11 | #include "arm-backtrace.h" 12 | #include 13 | #include 14 | 15 | void dump() 16 | { 17 | void* array[128]; 18 | int size = 0; 19 | int i = 0; 20 | char** strings = NULL; 21 | size = backtrace_arm(array, 128); 22 | strings = backtrace_symbols_arm(array, size); 23 | 24 | for (i = 0; i < size; i++) 25 | printf("%d: %s\n", i+1, strings[i]); 26 | 27 | free(strings); 28 | } 29 | 30 | class A 31 | { 32 | public: 33 | A(){;} 34 | ~A(){;} 35 | void AFunc() 36 | { 37 | printf("Hello!\n"); 38 | dump(); 39 | } 40 | }; 41 | 42 | class Caller 43 | { 44 | public: 45 | Caller(){;} 46 | ~Caller(){;} 47 | void CFunc() 48 | { 49 | A a; 50 | a.AFunc(); 51 | } 52 | }; 53 | 54 | void f1() {Caller c;c.CFunc();}; 55 | void f2() {f1();} 56 | void f3() {f2();} 57 | void f4() {f3();} 58 | void f5() {f4();} 59 | void f6() {f5();} 60 | void f7() {f6();} 61 | void f8() {f7();} 62 | void f9() {f8();} 63 | void f10() {f9();} 64 | void f11() {f10();} 65 | void f12() {f11();} 66 | void f13() {f12();} 67 | void f14() {f13();} 68 | void f15() {f14();} 69 | void f16() {f15();} 70 | 71 | int main() 72 | { 73 | f16(); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /arm-backtrace.c: -------------------------------------------------------------------------------- 1 | /******************************************** 2 | * 3 | * @file arm-backtrace.c 4 | * @author wuwc.zeno@inesa-e.com 5 | * @changelog: 6 | * 2014/06/24 create the file 7 | * 8 | * 9 | *******************************************/ 10 | 11 | #define _GNU_SOURCE 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "arm-backtrace.h" 17 | #include 18 | #include 19 | 20 | int backtrace_arm(void **array, int size) 21 | { 22 | if (size <= 0) 23 | return 0; 24 | 25 | int* fp = 0; 26 | int* nfp = 0; 27 | int ret = 0; 28 | int cnt = 0; 29 | 30 | __asm__ __volatile 31 | ( 32 | "mov %0, fp\n" 33 | : "=r"(fp) 34 | ); 35 | 36 | //printf("fp: 0x%x\n", fp); 37 | //printf("*fp: 0x%x\n", *fp); 38 | //printf("*(fp-1): 0x%x\n", *(fp-1)); 39 | //printf("*(fp-3): 0x%x\n", (*(fp-3))); 40 | 41 | if ((fp-1) != 0) 42 | array[cnt++] = (void *)(*(fp-1)); 43 | else 44 | { 45 | printf("fp-1 assert....\n"); 46 | return -1; 47 | } 48 | //printf("*(fp-3): 0x%x\n", (*(fp-3))); 49 | 50 | if ((fp-3) != 0) 51 | nfp = (int *)(*(fp-3)); 52 | else 53 | { 54 | printf("fp-3 assert....\n"); 55 | return -1; 56 | } 57 | //printf("nfp: 0x%x\n", nfp); 58 | //printf("nfp-3: 0x%x\n", nfp - 3); 59 | //printf("*nfp-3: 0x%x\n", *(nfp - 3)); 60 | while((cnt <= size) && (nfp > 0)) 61 | { 62 | array[cnt++] = (void *)*(nfp - 1); 63 | //printf("%d: %s\n", cnt-1, strings[cnt-1]); 64 | //free(strings); 65 | if ((nfp-3) != 0 && *(nfp-3) != 0) 66 | { 67 | //printf("nfp - 3: %d\n", (int)(nfp - 3)); 68 | //printf("*(nfp-3): %d\n", *(nfp-3)); 69 | nfp = (int *)(*(nfp-3)); 70 | } 71 | else 72 | { 73 | printf("nfp-3 assert....\n"); 74 | break ; 75 | } 76 | } 77 | 78 | 79 | ret = ((cnt <= size) ? cnt : size); 80 | 81 | return ret; 82 | } 83 | 84 | char ** backtrace_symbols_arm(void *const *array, int size) 85 | { 86 | Dl_info dlinfo[size]; 87 | int dlinfop[size]; 88 | int cnt; 89 | size_t total_size = 0; 90 | char **res; 91 | 92 | // 从函数返回地址获得函数名 93 | for (cnt = 0; cnt < size; ++cnt) 94 | { 95 | dlinfop[cnt] = dladdr (array[cnt], &dlinfo[cnt]); 96 | if (dlinfop[cnt] && dlinfo[cnt].dli_fname && dlinfo[cnt].dli_fname[0] != '\0') 97 | // 文件名(入口)+偏移 98 | total_size += (strlen (dlinfo[cnt].dli_fname ?: "") 99 | + (dlinfo[cnt].dli_sname ? strlen (dlinfo[cnt].dli_sname) + 3 + 8 + 3 : 1) 100 | + 8 + 5); 101 | else 102 | total_size += 5 + 8; 103 | } 104 | 105 | 106 | // 返回值,需要用户free 107 | res = (char **) malloc (size * sizeof (char *) + total_size); 108 | if (res != NULL) 109 | { 110 | char *last = (char *) (res + size); 111 | 112 | for (cnt = 0; cnt < size; ++cnt) 113 | { 114 | res[cnt] = last; 115 | 116 | if (dlinfop[cnt] && dlinfo[cnt].dli_fname && dlinfo[cnt].dli_fname[0] != '\0') 117 | { 118 | char buf[20]; 119 | 120 | if (array[cnt] >= (void *) dlinfo[cnt].dli_saddr) 121 | sprintf (buf, "+%#lx", \ 122 | (unsigned long)(array[cnt] - dlinfo[cnt].dli_saddr)); 123 | else 124 | sprintf (buf, "-%#lx", \ 125 | (unsigned long)(dlinfo[cnt].dli_saddr - array[cnt])); 126 | 127 | last += 1 + sprintf (last, "%s%s%s%s%s[%p]", 128 | dlinfo[cnt].dli_fname ?: "??", 129 | dlinfo[cnt].dli_sname ? "(" : "", 130 | dlinfo[cnt].dli_sname ?: "?", 131 | dlinfo[cnt].dli_sname ? buf : "?", 132 | dlinfo[cnt].dli_sname ? ") " : " ", 133 | array[cnt]); 134 | } 135 | else 136 | last += 1 + sprintf (last, "[%p]", array[cnt]); 137 | } 138 | assert (last <= (char *) res + size * sizeof (char *) + total_size); 139 | } 140 | 141 | return res; 142 | } 143 | --------------------------------------------------------------------------------