146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris/* 246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * Copyright (C) 2014 The Android Open Source Project 346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * 446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * you may not use this file except in compliance with the License. 646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * You may obtain a copy of the License at 746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * 846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * 1046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * Unless required by applicable law or agreed to in writing, software 1146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 1246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * See the License for the specific language governing permissions and 1446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris * limitations under the License. 1546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris */ 1646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 17cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn#define LOG_TAG "backtrace-map" 18cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn 1946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#include <ctype.h> 20ec2ff8c176d795656e69aecfce9650db40bef60bChih-Hung Hsieh#include <inttypes.h> 212c43cff01d1271be451671567955158629b23670Christopher Ferris#include <stdint.h> 2246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#include <sys/types.h> 2346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#include <unistd.h> 2446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 2530f991f251940be3ed11566fb71139852286f68aMark Salyzyn#include <log/log.h> 2630f991f251940be3ed11566fb71139852286f68aMark Salyzyn 27e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughes#include <android-base/stringprintf.h> 28e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughes#include <backtrace/Backtrace.h> 2946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#include <backtrace/BacktraceMap.h> 30e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughes#include <backtrace/backtrace_constants.h> 3146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 32df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#include "thread_utils.h" 33df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 34e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughesusing android::base::StringPrintf; 35e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughes 36e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughesstd::string backtrace_map_t::Name() const { 37e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughes if (!name.empty()) return name; 38e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughes if (start == 0 && end == 0) return ""; 39e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughes return StringPrintf("<anonymous:%" PRIPTR ">", start); 40e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughes} 41e1415a5c3b3e279fd6cfb6a7ee73ddc98bbec2aeElliott Hughes 4246756821c4fe238f12a6e5ea18c356398f8d8795Christopher FerrisBacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) { 4346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris if (pid_ < 0) { 4446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris pid_ = getpid(); 4546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 4646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris} 4746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 4846756821c4fe238f12a6e5ea18c356398f8d8795Christopher FerrisBacktraceMap::~BacktraceMap() { 4946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris} 5046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 517937a36c8e24ef2dc5105a2a6b67f395934b2e2fChristopher Ferrisvoid BacktraceMap::FillIn(uint64_t addr, backtrace_map_t* map) { 523a14004c7f521cf2ca6dfea182fa7441e77c97e7Christopher Ferris ScopedBacktraceMapIteratorLock lock(this); 53b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris for (auto it = begin(); it != end(); ++it) { 54b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris const backtrace_map_t* entry = *it; 55b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris if (addr >= entry->start && addr < entry->end) { 56b7de5f542925216dbb8b7124260d2915570598d1Christopher Ferris *map = *entry; 5712385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris return; 5846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 5946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 6012385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris *map = {}; 6146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris} 6246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 6346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrisbool BacktraceMap::ParseLine(const char* line, backtrace_map_t* map) { 64ec2ff8c176d795656e69aecfce9650db40bef60bChih-Hung Hsieh uint64_t start; 65ec2ff8c176d795656e69aecfce9650db40bef60bChih-Hung Hsieh uint64_t end; 6646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris char permissions[5]; 6746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris int name_pos; 6846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 6946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#if defined(__APPLE__) 7046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris// Mac OS vmmap(1) output: 7146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris// __TEXT 0009f000-000a1000 [ 8K 8K] r-x/rwx SM=COW /Volumes/android/dalvik-dev/out/host/darwin-x86/bin/libcorkscrew_test\n 7246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris// 012345678901234567890123456789012345678901234567890123456789 7346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris// 0 1 2 3 4 5 74ec2ff8c176d795656e69aecfce9650db40bef60bChih-Hung Hsieh if (sscanf(line, "%*21c %" SCNx64 "-%" SCNx64 " [%*13c] %3c/%*3c SM=%*3c %n", 7546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris &start, &end, permissions, &name_pos) != 3) { 7646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#else 7746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris// Linux /proc/<pid>/maps lines: 7846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so\n 7946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris// 012345678901234567890123456789012345678901234567890123456789 8046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris// 0 1 2 3 4 5 81ec2ff8c176d795656e69aecfce9650db40bef60bChih-Hung Hsieh if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %4s %*x %*x:%*x %*d %n", 8246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris &start, &end, permissions, &name_pos) != 3) { 8346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#endif 8446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris return false; 8546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 8646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 8746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris map->start = start; 8846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris map->end = end; 8946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris map->flags = PROT_NONE; 9046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris if (permissions[0] == 'r') { 9146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris map->flags |= PROT_READ; 9246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 9346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris if (permissions[1] == 'w') { 9446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris map->flags |= PROT_WRITE; 9546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 9646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris if (permissions[2] == 'x') { 9746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris map->flags |= PROT_EXEC; 9846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 9946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 10046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris map->name = line+name_pos; 10146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris if (!map->name.empty() && map->name[map->name.length()-1] == '\n') { 10246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris map->name.erase(map->name.length()-1); 10346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 10446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 10546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s", 106f4b0b7971c0333b7331c2f54384af5de0260ae75Colin Cross reinterpret_cast<void*>(map->start), reinterpret_cast<void*>(map->end), 107f4b0b7971c0333b7331c2f54384af5de0260ae75Colin Cross map->flags, map->name.c_str()); 10846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris return true; 10946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris} 11046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 11146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferrisbool BacktraceMap::Build() { 11246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#if defined(__APPLE__) 11346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris char cmd[sizeof(pid_t)*3 + sizeof("vmmap -w -resident -submap -allSplitLibs -interleaved ") + 1]; 11446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#else 11546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris char path[sizeof(pid_t)*3 + sizeof("/proc//maps") + 1]; 11646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#endif 11746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris char line[1024]; 11846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 11946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#if defined(__APPLE__) 12046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris // cmd is guaranteed to always be big enough to hold this string. 121b8c72957f072a687a4fb99dd7f2423d3f86e70d2Christopher Ferris snprintf(cmd, sizeof(cmd), "vmmap -w -resident -submap -allSplitLibs -interleaved %d", pid_); 12246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris FILE* fp = popen(cmd, "r"); 12346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#else 12446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris // path is guaranteed to always be big enough to hold this string. 125b8c72957f072a687a4fb99dd7f2423d3f86e70d2Christopher Ferris snprintf(path, sizeof(path), "/proc/%d/maps", pid_); 12646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris FILE* fp = fopen(path, "r"); 12746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#endif 1282c43cff01d1271be451671567955158629b23670Christopher Ferris if (fp == nullptr) { 12946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris return false; 13046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 13146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 13246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris while(fgets(line, sizeof(line), fp)) { 13346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris backtrace_map_t map; 13446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris if (ParseLine(line, &map)) { 13546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris maps_.push_back(map); 13646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 13746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris } 13846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#if defined(__APPLE__) 13946756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris pclose(fp); 14046756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#else 14146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris fclose(fp); 14246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#endif 14346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris 14446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris return true; 14546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris} 146df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 147df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#if defined(__APPLE__) 148df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris// Corkscrew and libunwind don't compile on the mac, so create a generic 149df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris// map object. 1505b439eaf938aa27b7db04225694be7d2a25af477Colin CrossBacktraceMap* BacktraceMap::Create(pid_t pid, bool /*uncached*/) { 151df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris BacktraceMap* map = new BacktraceMap(pid); 152df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris if (!map->Build()) { 153df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris delete map; 1542c43cff01d1271be451671567955158629b23670Christopher Ferris return nullptr; 155df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris } 156df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris return map; 157df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris} 158df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#endif 159