2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define LOG_TAG "CallStack"
33 #include <utils/Log.h>
34 #include <utils/Errors.h>
35 #include <utils/CallStack.h>
36 #include <utils/threads.h>
39 /*****************************************************************************/
47 } stack_crawl_state_t;
50 _Unwind_Reason_Code trace_function(_Unwind_Context *context, void *arg)
52 stack_crawl_state_t* state = (stack_crawl_state_t*)arg;
54 void* ip = (void*)_Unwind_GetIP(context);
65 return _URC_NO_REASON;
69 int backtrace(const void** addrs, size_t ignore, size_t size)
71 stack_crawl_state_t state;
73 state.ignore = ignore;
75 _Unwind_Backtrace(trace_function, (void*)&state);
76 return size - state.count;
79 /*****************************************************************************/
82 const char *lookup_symbol(const void* addr, void **offset, char* name, size_t bufSize)
86 if (dladdr(addr, &info)) {
87 *offset = info.dli_saddr;
88 return info.dli_sname;
95 int32_t linux_gcc_demangler(const char *mangled_name, char *unmangled_name, size_t buffersize)
100 char *demangled = abi::__cxa_demangle(mangled_name, 0, &out_len, &status);
103 if (out_len < buffersize) memcpy(unmangled_name, demangled, out_len);
113 /*****************************************************************************/
117 struct mapinfo *next;
123 const char *map_to_name(uint64_t pc, const char* def, uint64_t* start) {
124 mapinfo* mi = getMapInfoList();
126 if ((pc >= mi->start) && (pc < mi->end)) {
138 mapinfo *parse_maps_line(char *line) {
140 int len = strlen(line);
141 if (len < 1) return 0;
143 if (len < 50) return 0;
144 if (line[20] != 'x') return 0;
145 mi = (mapinfo*)malloc(sizeof(mapinfo) + (len - 47));
146 if (mi == 0) return 0;
147 mi->start = strtoull(line, 0, 16);
148 mi->end = strtoull(line + 9, 0, 16);
150 strcpy(mi->name, line + 49);
154 mapinfo* getMapInfoList() {
155 Mutex::Autolock _l(mLock);
159 sprintf(data, "/proc/%d/maps", getpid());
160 fp = fopen(data, "r");
162 while(fgets(data, 1024, fp)) {
163 mapinfo *mi = parse_maps_line(data);
176 static MapInfo sMapInfo;
185 mapinfo *next = milist->next;
191 static const char *mapAddressToName(const void* pc, const char* def,
195 char const* name = sMapInfo.map_to_name(uint64_t(uintptr_t(pc)), def, &s);
204 /*****************************************************************************/
206 MapInfo MapInfo::sMapInfo;
208 /*****************************************************************************/
210 CallStack::CallStack()
215 CallStack::CallStack(const CallStack& rhs)
219 memcpy(mStack, rhs.mStack, mCount*sizeof(void*));
223 CallStack::~CallStack()
227 CallStack& CallStack::operator = (const CallStack& rhs)
231 memcpy(mStack, rhs.mStack, mCount*sizeof(void*));
236 bool CallStack::operator == (const CallStack& rhs) const {
237 if (mCount != rhs.mCount)
239 return !mCount || (memcmp(mStack, rhs.mStack, mCount*sizeof(void*)) == 0);
242 bool CallStack::operator != (const CallStack& rhs) const {
243 return !operator == (rhs);
246 bool CallStack::operator < (const CallStack& rhs) const {
247 if (mCount != rhs.mCount)
248 return mCount < rhs.mCount;
249 return memcmp(mStack, rhs.mStack, mCount*sizeof(void*)) < 0;
252 bool CallStack::operator >= (const CallStack& rhs) const {
253 return !operator < (rhs);
256 bool CallStack::operator > (const CallStack& rhs) const {
257 if (mCount != rhs.mCount)
258 return mCount > rhs.mCount;
259 return memcmp(mStack, rhs.mStack, mCount*sizeof(void*)) > 0;
262 bool CallStack::operator <= (const CallStack& rhs) const {
263 return !operator > (rhs);
266 const void* CallStack::operator [] (int index) const {
267 if (index >= int(mCount))
269 return mStack[index];
273 void CallStack::clear()
278 void CallStack::update(int32_t ignoreDepth, int32_t maxDepth)
280 if (maxDepth > MAX_DEPTH)
281 maxDepth = MAX_DEPTH;
282 mCount = backtrace(mStack, ignoreDepth, maxDepth);
285 // Return the stack frame name on the designated level
286 String8 CallStack::toStringSingleLevel(const char* prefix, int32_t level) const
295 const void* ip = mStack[level];
298 if (prefix) res.append(prefix);
299 snprintf(tmp1, 32, "#%02d ", level);
302 const char* name = lookup_symbol(ip, &offs, namebuf, sizeof(namebuf));
304 if (linux_gcc_demangler(name, tmp, 256) != 0)
306 snprintf(tmp1, 32, "0x%p: <", ip);
307 snprintf(tmp2, 32, ">+0x%p", offs);
312 void const* start = 0;
313 name = MapInfo::mapAddressToName(ip, "<unknown>", &start);
314 snprintf(tmp, 256, "pc %08lx %s",
315 long(uintptr_t(ip)-uintptr_t(start)), name);
323 // Dump a stack trace to the log
324 void CallStack::dump(const char* prefix) const
327 * Sending a single long log may be truncated since the stack levels can
328 * get very deep. So we request function names of each frame individually.
330 for (int i=0; i<int(mCount); i++) {
331 LOGD("%s", toStringSingleLevel(prefix, i).string());
335 // Return a string (possibly very long) containing the complete stack trace
336 String8 CallStack::toString(const char* prefix) const
340 for (int i=0; i<int(mCount); i++) {
341 res.append(toStringSingleLevel(prefix, i).string());
347 /*****************************************************************************/
349 }; // namespace android