1
+ /* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
2
+ miniob is licensed under Mulan PSL v2.
3
+ You can use this software according to the terms and conditions of the Mulan PSL v2.
4
+ You may obtain a copy of Mulan PSL v2 at:
5
+ http://license.coscl.org.cn/MulanPSL2
6
+ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
7
+ EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
8
+ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
9
+ See the Mulan PSL v2 for more details. */
10
+
11
+ //
12
+ // Created by WangYunlai on 2024
13
+ //
14
+
15
+ #include < stdint.h>
16
+ #include < stdio.h>
17
+ #include < execinfo.h>
18
+ #include < inttypes.h>
19
+ #include " common/lang/vector.h"
20
+
21
+ namespace common {
22
+
23
+ struct ProcMapSegment
24
+ {
25
+ uint64_t start_address;
26
+ uint64_t end_address;
27
+ };
28
+
29
+ class ProcMap
30
+ {
31
+ public:
32
+ ProcMap () = default ;
33
+ ~ProcMap () = default ;
34
+
35
+ int parse ();
36
+ int parse_file (const char *file_name);
37
+
38
+ const ProcMapSegment *get_segment (const uint64_t address) const ;
39
+
40
+ uint64_t get_offset (const uint64_t address) const ;
41
+
42
+ private:
43
+ vector<ProcMapSegment> segments_;
44
+ };
45
+
46
+ int ProcMap::parse ()
47
+ {
48
+ const char *file_name = " /proc/self/maps" ;
49
+ return parse_file (file_name);
50
+ }
51
+
52
+ int ProcMap::parse_file (const char *file_name)
53
+ {
54
+ FILE *fp = fopen (file_name, " r" );
55
+ if (fp == nullptr ) {
56
+ return -1 ;
57
+ }
58
+
59
+ ProcMapSegment segment;
60
+ char line[1024 ] = {0 };
61
+ uint64_t start, end, inode, offset, major, minor;
62
+ char perms[8 ];
63
+ char path[257 ];
64
+
65
+ while (fgets (line, sizeof (line), fp) != nullptr ) {
66
+
67
+ int ret = sscanf (line, " %" PRIx64 " -%" PRIx64 " %4s %" PRIx64 " %" PRIx64 " :%" PRIx64 " %" PRIu64 " %255s" ,
68
+ &start, &end, perms, &offset, &major, &minor, &inode, path);
69
+ if (ret < 8 || perms[2 ] != ' x' ) {
70
+ continue ;
71
+ }
72
+
73
+ segment.start_address = start;
74
+ segment.end_address = end;
75
+
76
+ segments_.push_back (segment);
77
+ }
78
+
79
+ fclose (fp);
80
+ return 0 ;
81
+ }
82
+
83
+ const ProcMapSegment *ProcMap::get_segment (const uint64_t address) const
84
+ {
85
+ for (const auto &segment : segments_) {
86
+ if (address >= segment.start_address && address < segment.end_address ) {
87
+ return &segment;
88
+ }
89
+ }
90
+
91
+ return nullptr ;
92
+ }
93
+
94
+ uint64_t ProcMap::get_offset (const uint64_t address) const
95
+ {
96
+ const ProcMapSegment *segment = get_segment (address);
97
+ if (segment == nullptr ) {
98
+ return address;
99
+ }
100
+
101
+ return address - segment->start_address ;
102
+ }
103
+
104
+ // ////////////////////////////////////////////////////////////////////////
105
+ static ProcMap g_proc_map;
106
+ int backtrace_init ()
107
+ {
108
+ return g_proc_map.parse ();
109
+ }
110
+
111
+ const char *lbt ()
112
+ {
113
+ constexpr int buffer_size = 100 ;
114
+ void *buffer[buffer_size];
115
+
116
+ constexpr int bt_buffer_size = 8192 ;
117
+ thread_local char backtrace_buffer[bt_buffer_size];
118
+
119
+ int size = backtrace (buffer, buffer_size);
120
+
121
+ char **symbol_array = nullptr ;
122
+ #ifdef LBT_SYMBOLS
123
+ /* 有些环境下,使用addr2line 无法根据地址输出符号 */
124
+ symbol_array = backtrace_symbols (buffer, size);
125
+ #endif // LBT_SYMBOLS
126
+
127
+ int offset = 0 ;
128
+ for (int i = 0 ; i < size && offset < bt_buffer_size - 1 ; i++) {
129
+ uint64_t address = reinterpret_cast <uint64_t >(buffer[i]);
130
+ address = g_proc_map.get_offset (address);
131
+ const char *format = (0 == i) ? " 0x%lx" : " 0x%lx" ;
132
+ offset += snprintf (backtrace_buffer + offset, sizeof (backtrace_buffer) - offset, format, address);
133
+
134
+ if (symbol_array != nullptr ) {
135
+ offset += snprintf (backtrace_buffer + offset, sizeof (backtrace_buffer) - offset, " %s" , symbol_array[i]);
136
+ }
137
+ }
138
+
139
+ if (symbol_array != nullptr ) {
140
+ free (symbol_array);
141
+ }
142
+ return backtrace_buffer;
143
+ }
144
+
145
+ } // namespace common
0 commit comments