1 /*
2  * Copyright (c) 2022-2024 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 
25 #include "dfx_define.h"
26 #include "dfx_log.h"
27 
28 #ifdef LOG_DOMAIN
29 #undef LOG_DOMAIN
30 #define LOG_DOMAIN 0xD002D11
31 #endif
32 
33 #ifdef LOG_TAG
34 #undef LOG_TAG
35 #define LOG_TAG "DfxFuncHook"
36 #endif
37 
38 #define MIN_FRAME 4
39 #define MAX_FRAME 64
40 #define BUF_SZ 512
41 
42 static pthread_mutex_t g_backtraceLock = PTHREAD_MUTEX_INITIALIZER;
43 
LogBacktrace(void)44 void LogBacktrace(void)
45 {
46     pthread_mutex_lock(&g_backtraceLock);
47     unw_context_t context;
48     unw_getcontext(&context);
49 
50     unw_cursor_t cursor;
51     unw_init_local(&cursor, &context);
52 
53     int index = 0;
54     unw_word_t pc;
55     unw_word_t prevPc;
56     bool shouldContinue = true;
57     while (true) {
58         if (index > MAX_FRAME) {
59             break;
60         }
61 
62         if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t*)(&pc))) {
63             break;
64         }
65 
66         if (index > MIN_FRAME && prevPc == pc) {
67             break;
68         }
69         prevPc = pc;
70         index++;
71 
72         if (!shouldContinue) {
73             break;
74         }
75 
76         int ret = unw_step(&cursor);
77         if (ret == 0) {
78             shouldContinue = false;
79         } else if (ret < 0) {
80             break;
81         }
82     }
83     pthread_mutex_unlock(&g_backtraceLock);
84 }