1df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris/* 2df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * Copyright (C) 2014 The Android Open Source Project 3df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * 4df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 5df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * you may not use this file except in compliance with the License. 6df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * You may obtain a copy of the License at 7df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * 8df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 9df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * 10df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * Unless required by applicable law or agreed to in writing, software 11df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 12df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * See the License for the specific language governing permissions and 14df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris * limitations under the License. 15df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris */ 16df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 172c43cff01d1271be451671567955158629b23670Christopher Ferris#include <stdint.h> 18ac2fe7eb81789274ab98573d0c4b0866bed1f254Dan Albert#include <stdlib.h> 19df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#include <sys/types.h> 20df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#include <unistd.h> 21df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 22df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#include <backtrace/BacktraceMap.h> 23df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 24df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#include <libunwind.h> 25df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 26e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris#include "BacktraceLog.h" 27df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris#include "UnwindMap.h" 28df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 29df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris//------------------------------------------------------------------------- 30df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris// libunwind has a single shared address space for the current process 31df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris// aka local. If multiple maps are created for the current pid, then 32df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris// only update the local address space once, and keep a reference count 33df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris// of maps using the same map cursor. 34df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris//------------------------------------------------------------------------- 35df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher FerrisUnwindMap::UnwindMap(pid_t pid) : BacktraceMap(pid) { 36d4c884330c384bbb06f9a0d1fee2d2ae2086521cChristopher Ferris unw_map_cursor_clear(&map_cursor_); 37d4c884330c384bbb06f9a0d1fee2d2ae2086521cChristopher Ferris} 38d4c884330c384bbb06f9a0d1fee2d2ae2086521cChristopher Ferris 39d4c884330c384bbb06f9a0d1fee2d2ae2086521cChristopher FerrisUnwindMapRemote::UnwindMapRemote(pid_t pid) : UnwindMap(pid) { 40df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris} 41df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 42d4c884330c384bbb06f9a0d1fee2d2ae2086521cChristopher FerrisUnwindMapRemote::~UnwindMapRemote() { 43e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris unw_map_cursor_destroy(&map_cursor_); 44e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris unw_map_cursor_clear(&map_cursor_); 45df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris} 46df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 47d4c884330c384bbb06f9a0d1fee2d2ae2086521cChristopher Ferrisbool UnwindMapRemote::GenerateMap() { 48df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris // Use the map_cursor information to construct the BacktraceMap data 49df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris // rather than reparsing /proc/self/maps. 50df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris unw_map_cursor_reset(&map_cursor_); 51e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 52df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris unw_map_t unw_map; 53e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris while (unw_map_cursor_get_next(&map_cursor_, &unw_map)) { 54df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris backtrace_map_t map; 55df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 56df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris map.start = unw_map.start; 57df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris map.end = unw_map.end; 58af67fb247540ef084a0b644e1d3bf225db4de6bdChristopher Ferris map.offset = unw_map.offset; 59329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris map.load_base = unw_map.load_base; 60df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris map.flags = unw_map.flags; 61df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris map.name = unw_map.path; 62df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 63df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris // The maps are in descending order, but we want them in ascending order. 64df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris maps_.push_front(map); 65df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris } 66df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 67df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris return true; 68df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris} 69df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris 70d4c884330c384bbb06f9a0d1fee2d2ae2086521cChristopher Ferrisbool UnwindMapRemote::Build() { 71e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris return (unw_map_cursor_create(&map_cursor_, pid_) == 0) && GenerateMap(); 72e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris} 73e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 74e29609106033a48a6128664668d22bf4fb42a7eeChristopher FerrisUnwindMapLocal::UnwindMapLocal() : UnwindMap(getpid()), map_created_(false) { 75e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris} 76e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 77e29609106033a48a6128664668d22bf4fb42a7eeChristopher FerrisUnwindMapLocal::~UnwindMapLocal() { 78e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris if (map_created_) { 79e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris unw_map_local_destroy(); 80e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris unw_map_cursor_clear(&map_cursor_); 81e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris } 82e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris} 83e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 84e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferrisbool UnwindMapLocal::GenerateMap() { 85e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris // It's possible for the map to be regenerated while this loop is occurring. 86e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris // If that happens, get the map again, but only try at most three times 87e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris // before giving up. 88e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris for (int i = 0; i < 3; i++) { 89e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris maps_.clear(); 90e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 91d4c884330c384bbb06f9a0d1fee2d2ae2086521cChristopher Ferris // Save the map data retrieved so we can tell if it changes. 92e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris unw_map_local_cursor_get(&map_cursor_); 93e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 94e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris unw_map_t unw_map; 95e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris int ret; 96e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris while ((ret = unw_map_local_cursor_get_next(&map_cursor_, &unw_map)) > 0) { 97e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris backtrace_map_t map; 98e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 99e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris map.start = unw_map.start; 100e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris map.end = unw_map.end; 101af67fb247540ef084a0b644e1d3bf225db4de6bdChristopher Ferris map.offset = unw_map.offset; 102329ed7dae49eba09bdf865dd999d1a7e73bb9687Christopher Ferris map.load_base = unw_map.load_base; 103e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris map.flags = unw_map.flags; 104e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris map.name = unw_map.path; 105e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 106e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris free(unw_map.path); 107e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 108e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris // The maps are in descending order, but we want them in ascending order. 109e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris maps_.push_front(map); 110e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris } 111e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris // Check to see if the map changed while getting the data. 112e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris if (ret != -UNW_EINVAL) { 113e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris return true; 114e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris } 115e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris } 116e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 117e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris BACK_LOGW("Unable to generate the map."); 118e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris return false; 119e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris} 120e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 121e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferrisbool UnwindMapLocal::Build() { 122e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris return (map_created_ = (unw_map_local_create() == 0)) && GenerateMap();; 123e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris} 124e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 12512385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferrisvoid UnwindMapLocal::FillIn(uintptr_t addr, backtrace_map_t* map) { 12612385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris BacktraceMap::FillIn(addr, map); 12712385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris if (!IsValid(*map)) { 128e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris // Check to see if the underlying map changed and regenerate the map 129e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris // if it did. 130e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris if (unw_map_local_cursor_valid(&map_cursor_) < 0) { 131e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris if (GenerateMap()) { 13212385e3ad085aa1ac06c26529b32b688503a9fcfChristopher Ferris BacktraceMap::FillIn(addr, map); 133e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris } 134e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris } 135e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris } 136e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris} 137e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris 138df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris//------------------------------------------------------------------------- 139df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris// BacktraceMap create function. 140df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris//------------------------------------------------------------------------- 141dda47b786835ef3689f06e24650eb65176e2dc5eChristopher FerrisBacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) { 142e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris BacktraceMap* map; 143dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris 144dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris if (uncached) { 145dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris // Force use of the base class to parse the maps when this call is made. 146dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris map = new BacktraceMap(pid); 147dda47b786835ef3689f06e24650eb65176e2dc5eChristopher Ferris } else if (pid == getpid()) { 148e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris map = new UnwindMapLocal(); 149e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris } else { 150d4c884330c384bbb06f9a0d1fee2d2ae2086521cChristopher Ferris map = new UnwindMapRemote(pid); 151e29609106033a48a6128664668d22bf4fb42a7eeChristopher Ferris } 152df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris if (!map->Build()) { 153df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris delete map; 1542c43cff01d1271be451671567955158629b23670Christopher Ferris return nullptr; 155df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris } 156df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris return map; 157df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris} 158