• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "dfx_hook_utils.h"
17 
18 #include <securec.h>
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <stdbool.h>
22 
23 #include <libunwind_i.h>
24 #include <libunwind_i-ohos.h>
25 #include <map_info.h>
26 
27 #include "dfx_define.h"
28 #include "dfx_log.h"
29 
30 #ifdef LOG_DOMAIN
31 #undef LOG_DOMAIN
32 #define LOG_DOMAIN 0xD002D11
33 #endif
34 
35 #ifdef LOG_TAG
36 #undef LOG_TAG
37 #define LOG_TAG "DfxFuncHook"
38 #endif
39 
40 #define MIN_FRAME 4
41 #define MAX_FRAME 64
42 #define BUF_SZ 512
43 
44 static pthread_mutex_t g_backtraceLock = PTHREAD_MUTEX_INITIALIZER;
45 
LogBacktrace(void)46 void LogBacktrace(void)
47 {
48     pthread_mutex_lock(&g_backtraceLock);
49     unw_addr_space_t as = NULL;
50     unw_init_local_address_space(&as);
51     if (as == NULL) {
52         pthread_mutex_unlock(&g_backtraceLock);
53         return;
54     }
55 
56     unw_context_t context;
57     unw_getcontext(&context);
58 
59     unw_cursor_t cursor;
60     unw_init_local_with_as(as, &cursor, &context);
61 
62     int index = 0;
63     unw_word_t pc;
64     unw_word_t relPc;
65     unw_word_t prevPc;
66     unw_word_t sz;
67     uint64_t start;
68     uint64_t end;
69     bool shouldContinue = true;
70     while (true) {
71         if (index > MAX_FRAME) {
72             break;
73         }
74 
75         if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t*)(&pc))) {
76             break;
77         }
78 
79         if (index > MIN_FRAME && prevPc == pc) {
80             break;
81         }
82         prevPc = pc;
83 
84         relPc = unw_get_rel_pc(&cursor);
85         struct map_info* mapInfo = unw_get_map(&cursor);
86         if (mapInfo == NULL && index > 1) {
87             break;
88         }
89 
90         sz = unw_get_previous_instr_sz(&cursor);
91         if (index != 0 && relPc > sz) {
92             relPc -= sz;
93             pc -= sz;
94         }
95 
96         char buf[BUF_SZ];
97         (void)memset_s(&buf, sizeof(buf), 0, sizeof(buf));
98         if (unw_get_symbol_info_by_pc(as, pc, BUF_SZ, buf, &start, &end) == 0) {
99             LOGI("#%02d %016p(%016p) %s(%s)\n", index, relPc, pc,
100                 mapInfo == NULL ? "Unknown" : mapInfo->path,
101                 buf);
102         } else {
103             LOGI("#%02d %016p(%016p) %s\n", index, relPc, pc,
104                 mapInfo == NULL ? "Unknown" : mapInfo->path);
105         }
106         index++;
107 
108         if (!shouldContinue) {
109             break;
110         }
111 
112         int ret = unw_step(&cursor);
113         if (ret == 0) {
114             shouldContinue = false;
115         } else if (ret < 0) {
116             break;
117         }
118     }
119     unw_destroy_local_address_space(as);
120     pthread_mutex_unlock(&g_backtraceLock);
121 }