1*eb293b8fSAndroid Build Coastguard Worker /* 2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project 3*eb293b8fSAndroid Build Coastguard Worker * 4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*eb293b8fSAndroid Build Coastguard Worker * 8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*eb293b8fSAndroid Build Coastguard Worker * 10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License. 15*eb293b8fSAndroid Build Coastguard Worker */ 16*eb293b8fSAndroid Build Coastguard Worker 17*eb293b8fSAndroid Build Coastguard Worker #pragma once 18*eb293b8fSAndroid Build Coastguard Worker 19*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h> 20*eb293b8fSAndroid Build Coastguard Worker 21*eb293b8fSAndroid Build Coastguard Worker #include <atomic> 22*eb293b8fSAndroid Build Coastguard Worker #include <memory> 23*eb293b8fSAndroid Build Coastguard Worker #include <mutex> 24*eb293b8fSAndroid Build Coastguard Worker #include <string> 25*eb293b8fSAndroid Build Coastguard Worker 26*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h> 27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/SharedString.h> 28*eb293b8fSAndroid Build Coastguard Worker 29*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack { 30*eb293b8fSAndroid Build Coastguard Worker 31*eb293b8fSAndroid Build Coastguard Worker class MemoryFileAtOffset; 32*eb293b8fSAndroid Build Coastguard Worker 33*eb293b8fSAndroid Build Coastguard Worker // Represents virtual memory map (as obtained from /proc/*/maps). 34*eb293b8fSAndroid Build Coastguard Worker // 35*eb293b8fSAndroid Build Coastguard Worker // Note that we have to be surprisingly careful with memory usage here, 36*eb293b8fSAndroid Build Coastguard Worker // since in system-wide profiling this data can take considerable space. 37*eb293b8fSAndroid Build Coastguard Worker // (for example, 400 process * 400 maps * 128 bytes = 20 MB + string data). 38*eb293b8fSAndroid Build Coastguard Worker class MapInfo { 39*eb293b8fSAndroid Build Coastguard Worker public: MapInfo(std::shared_ptr<MapInfo> & prev_map,uint64_t start,uint64_t end,uint64_t offset,uint64_t flags,SharedString name)40*eb293b8fSAndroid Build Coastguard Worker MapInfo(std::shared_ptr<MapInfo>& prev_map, uint64_t start, uint64_t end, uint64_t offset, 41*eb293b8fSAndroid Build Coastguard Worker uint64_t flags, SharedString name) 42*eb293b8fSAndroid Build Coastguard Worker : start_(start), 43*eb293b8fSAndroid Build Coastguard Worker end_(end), 44*eb293b8fSAndroid Build Coastguard Worker offset_(offset), 45*eb293b8fSAndroid Build Coastguard Worker flags_(flags), 46*eb293b8fSAndroid Build Coastguard Worker name_(name), 47*eb293b8fSAndroid Build Coastguard Worker elf_fields_(nullptr), 48*eb293b8fSAndroid Build Coastguard Worker prev_map_(prev_map) {} MapInfo(uint64_t start,uint64_t end,uint64_t offset,uint64_t flags,SharedString name)49*eb293b8fSAndroid Build Coastguard Worker MapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, SharedString name) 50*eb293b8fSAndroid Build Coastguard Worker : start_(start), 51*eb293b8fSAndroid Build Coastguard Worker end_(end), 52*eb293b8fSAndroid Build Coastguard Worker offset_(offset), 53*eb293b8fSAndroid Build Coastguard Worker flags_(flags), 54*eb293b8fSAndroid Build Coastguard Worker name_(name), 55*eb293b8fSAndroid Build Coastguard Worker elf_fields_(nullptr) {} 56*eb293b8fSAndroid Build Coastguard Worker Create(std::shared_ptr<MapInfo> & prev_map,uint64_t start,uint64_t end,uint64_t offset,uint64_t flags,SharedString name)57*eb293b8fSAndroid Build Coastguard Worker static inline std::shared_ptr<MapInfo> Create(std::shared_ptr<MapInfo>& prev_map, 58*eb293b8fSAndroid Build Coastguard Worker uint64_t start, uint64_t end, uint64_t offset, 59*eb293b8fSAndroid Build Coastguard Worker uint64_t flags, SharedString name) { 60*eb293b8fSAndroid Build Coastguard Worker auto map_info = std::make_shared<MapInfo>(prev_map, start, end, offset, flags, name); 61*eb293b8fSAndroid Build Coastguard Worker if (prev_map) { 62*eb293b8fSAndroid Build Coastguard Worker prev_map->next_map_ = map_info; 63*eb293b8fSAndroid Build Coastguard Worker } 64*eb293b8fSAndroid Build Coastguard Worker return map_info; 65*eb293b8fSAndroid Build Coastguard Worker } Create(uint64_t start,uint64_t end,uint64_t offset,uint64_t flags,SharedString name)66*eb293b8fSAndroid Build Coastguard Worker static inline std::shared_ptr<MapInfo> Create(uint64_t start, uint64_t end, uint64_t offset, 67*eb293b8fSAndroid Build Coastguard Worker uint64_t flags, SharedString name) { 68*eb293b8fSAndroid Build Coastguard Worker return std::make_shared<MapInfo>(start, end, offset, flags, name); 69*eb293b8fSAndroid Build Coastguard Worker } 70*eb293b8fSAndroid Build Coastguard Worker 71*eb293b8fSAndroid Build Coastguard Worker ~MapInfo(); 72*eb293b8fSAndroid Build Coastguard Worker 73*eb293b8fSAndroid Build Coastguard Worker // Cached data for mapped ELF files. 74*eb293b8fSAndroid Build Coastguard Worker // We allocate this structure lazily since there are much fewer ELFs than maps. 75*eb293b8fSAndroid Build Coastguard Worker struct ElfFields { ElfFieldsElfFields76*eb293b8fSAndroid Build Coastguard Worker ElfFields() : load_bias_(UINT64_MAX), build_id_(0) {} 77*eb293b8fSAndroid Build Coastguard Worker 78*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Elf> elf_; 79*eb293b8fSAndroid Build Coastguard Worker // The offset of the beginning of this mapping to the beginning of the 80*eb293b8fSAndroid Build Coastguard Worker // ELF file. 81*eb293b8fSAndroid Build Coastguard Worker // elf_offset == offset - elf_start_offset. 82*eb293b8fSAndroid Build Coastguard Worker // This value is only non-zero if the offset is non-zero but there is 83*eb293b8fSAndroid Build Coastguard Worker // no elf signature found at that offset. 84*eb293b8fSAndroid Build Coastguard Worker uint64_t elf_offset_ = 0; 85*eb293b8fSAndroid Build Coastguard Worker // This value is the offset into the file of the map in memory that is the 86*eb293b8fSAndroid Build Coastguard Worker // start of the elf. This is not equal to offset when the linker splits 87*eb293b8fSAndroid Build Coastguard Worker // shared libraries into a read-only and read-execute map. 88*eb293b8fSAndroid Build Coastguard Worker uint64_t elf_start_offset_ = 0; 89*eb293b8fSAndroid Build Coastguard Worker 90*eb293b8fSAndroid Build Coastguard Worker std::atomic_uint64_t load_bias_; 91*eb293b8fSAndroid Build Coastguard Worker 92*eb293b8fSAndroid Build Coastguard Worker // This is a pointer to a new'd std::string. 93*eb293b8fSAndroid Build Coastguard Worker // Using an atomic value means that we don't need to lock and will 94*eb293b8fSAndroid Build Coastguard Worker // make it easier to move to a fine grained lock in the future. 95*eb293b8fSAndroid Build Coastguard Worker std::atomic<SharedString*> build_id_; 96*eb293b8fSAndroid Build Coastguard Worker 97*eb293b8fSAndroid Build Coastguard Worker // Set to true if the elf file data is coming from memory. 98*eb293b8fSAndroid Build Coastguard Worker bool memory_backed_elf_ = false; 99*eb293b8fSAndroid Build Coastguard Worker 100*eb293b8fSAndroid Build Coastguard Worker // Protect the creation of the elf object. 101*eb293b8fSAndroid Build Coastguard Worker std::mutex elf_mutex_; 102*eb293b8fSAndroid Build Coastguard Worker }; 103*eb293b8fSAndroid Build Coastguard Worker 104*eb293b8fSAndroid Build Coastguard Worker // True if the file named by this map is not actually readable and the 105*eb293b8fSAndroid Build Coastguard Worker // elf is using the data in memory. 106*eb293b8fSAndroid Build Coastguard Worker bool ElfFileNotReadable(); 107*eb293b8fSAndroid Build Coastguard Worker 108*eb293b8fSAndroid Build Coastguard Worker // This is the previous map with the same name that is not empty and with 109*eb293b8fSAndroid Build Coastguard Worker // a 0 offset. For example, this set of maps: 110*eb293b8fSAndroid Build Coastguard Worker // 1000-2000 r--p 000000 00:00 0 libc.so 111*eb293b8fSAndroid Build Coastguard Worker // 2000-3000 ---p 000000 00:00 0 112*eb293b8fSAndroid Build Coastguard Worker // 3000-4000 r-xp 003000 00:00 0 libc.so 113*eb293b8fSAndroid Build Coastguard Worker // The last map's prev_map would point to the 2000-3000 map, while 114*eb293b8fSAndroid Build Coastguard Worker // GetPrevRealMap() would point to the 1000-2000 map. 115*eb293b8fSAndroid Build Coastguard Worker // NOTE: If a map is encountered that has a non-zero offset, or has a 116*eb293b8fSAndroid Build Coastguard Worker // a name different from the current map, then GetPrevRealMap() 117*eb293b8fSAndroid Build Coastguard Worker // returns nullptr. 118*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<MapInfo> GetPrevRealMap(); 119*eb293b8fSAndroid Build Coastguard Worker // This is the next map with the same name that is not empty and with 120*eb293b8fSAndroid Build Coastguard Worker // a 0 offset. For the example above, the first map's GetNextRealMap() 121*eb293b8fSAndroid Build Coastguard Worker // would be the 3000-4000 map. 122*eb293b8fSAndroid Build Coastguard Worker // NOTE: If a map is encountered that has a non-zero offset, or has a 123*eb293b8fSAndroid Build Coastguard Worker // a name different from the current map, then GetNextRealMap() 124*eb293b8fSAndroid Build Coastguard Worker // returns nullptr. 125*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<MapInfo> GetNextRealMap(); 126*eb293b8fSAndroid Build Coastguard Worker 127*eb293b8fSAndroid Build Coastguard Worker // This is guaranteed to give out the Elf object associated with the 128*eb293b8fSAndroid Build Coastguard Worker // object. The invariant is that once the Elf object is set under the 129*eb293b8fSAndroid Build Coastguard Worker // lock in a MapInfo object it never changes and is not freed until 130*eb293b8fSAndroid Build Coastguard Worker // the MapInfo object is destructed. GetElfObj()131*eb293b8fSAndroid Build Coastguard Worker inline Elf* GetElfObj() { 132*eb293b8fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> guard(elf_mutex()); 133*eb293b8fSAndroid Build Coastguard Worker return elf().get(); 134*eb293b8fSAndroid Build Coastguard Worker } 135*eb293b8fSAndroid Build Coastguard Worker start()136*eb293b8fSAndroid Build Coastguard Worker inline uint64_t start() const { return start_; } set_start(uint64_t value)137*eb293b8fSAndroid Build Coastguard Worker inline void set_start(uint64_t value) { start_ = value; } 138*eb293b8fSAndroid Build Coastguard Worker end()139*eb293b8fSAndroid Build Coastguard Worker inline uint64_t end() const { return end_; } set_end(uint64_t value)140*eb293b8fSAndroid Build Coastguard Worker inline void set_end(uint64_t value) { end_ = value; } 141*eb293b8fSAndroid Build Coastguard Worker offset()142*eb293b8fSAndroid Build Coastguard Worker inline uint64_t offset() const { return offset_; } set_offset(uint64_t value)143*eb293b8fSAndroid Build Coastguard Worker inline void set_offset(uint64_t value) { offset_ = value; } 144*eb293b8fSAndroid Build Coastguard Worker flags()145*eb293b8fSAndroid Build Coastguard Worker inline uint16_t flags() const { return flags_; } set_flags(uint16_t value)146*eb293b8fSAndroid Build Coastguard Worker inline void set_flags(uint16_t value) { flags_ = value; } 147*eb293b8fSAndroid Build Coastguard Worker name()148*eb293b8fSAndroid Build Coastguard Worker inline SharedString& name() { return name_; } set_name(SharedString & value)149*eb293b8fSAndroid Build Coastguard Worker inline void set_name(SharedString& value) { name_ = value; } set_name(const char * value)150*eb293b8fSAndroid Build Coastguard Worker inline void set_name(const char* value) { name_ = value; } 151*eb293b8fSAndroid Build Coastguard Worker elf()152*eb293b8fSAndroid Build Coastguard Worker inline std::shared_ptr<Elf>& elf() { return GetElfFields().elf_; } set_elf(std::shared_ptr<Elf> & value)153*eb293b8fSAndroid Build Coastguard Worker inline void set_elf(std::shared_ptr<Elf>& value) { GetElfFields().elf_ = value; } set_elf(Elf * value)154*eb293b8fSAndroid Build Coastguard Worker inline void set_elf(Elf* value) { GetElfFields().elf_.reset(value); } 155*eb293b8fSAndroid Build Coastguard Worker elf_offset()156*eb293b8fSAndroid Build Coastguard Worker inline uint64_t elf_offset() { return GetElfFields().elf_offset_; } set_elf_offset(uint64_t value)157*eb293b8fSAndroid Build Coastguard Worker inline void set_elf_offset(uint64_t value) { GetElfFields().elf_offset_ = value; } 158*eb293b8fSAndroid Build Coastguard Worker elf_start_offset()159*eb293b8fSAndroid Build Coastguard Worker inline uint64_t elf_start_offset() { return GetElfFields().elf_start_offset_; } set_elf_start_offset(uint64_t value)160*eb293b8fSAndroid Build Coastguard Worker inline void set_elf_start_offset(uint64_t value) { GetElfFields().elf_start_offset_ = value; } 161*eb293b8fSAndroid Build Coastguard Worker load_bias()162*eb293b8fSAndroid Build Coastguard Worker inline std::atomic_uint64_t& load_bias() { return GetElfFields().load_bias_; } set_load_bias(uint64_t value)163*eb293b8fSAndroid Build Coastguard Worker inline void set_load_bias(uint64_t value) { GetElfFields().load_bias_ = value; } 164*eb293b8fSAndroid Build Coastguard Worker build_id()165*eb293b8fSAndroid Build Coastguard Worker inline std::atomic<SharedString*>& build_id() { return GetElfFields().build_id_; } set_build_id(SharedString * value)166*eb293b8fSAndroid Build Coastguard Worker inline void set_build_id(SharedString* value) { GetElfFields().build_id_ = value; } 167*eb293b8fSAndroid Build Coastguard Worker memory_backed_elf()168*eb293b8fSAndroid Build Coastguard Worker inline bool memory_backed_elf() { return GetElfFields().memory_backed_elf_; } set_memory_backed_elf(bool value)169*eb293b8fSAndroid Build Coastguard Worker inline void set_memory_backed_elf(bool value) { GetElfFields().memory_backed_elf_ = value; } 170*eb293b8fSAndroid Build Coastguard Worker prev_map()171*eb293b8fSAndroid Build Coastguard Worker inline std::shared_ptr<MapInfo> prev_map() const { return prev_map_.lock(); } set_prev_map(std::shared_ptr<MapInfo> & value)172*eb293b8fSAndroid Build Coastguard Worker inline void set_prev_map(std::shared_ptr<MapInfo>& value) { prev_map_ = value; } 173*eb293b8fSAndroid Build Coastguard Worker next_map()174*eb293b8fSAndroid Build Coastguard Worker inline std::shared_ptr<MapInfo> next_map() const { return next_map_.lock(); } set_next_map(std::shared_ptr<MapInfo> & value)175*eb293b8fSAndroid Build Coastguard Worker inline void set_next_map(std::shared_ptr<MapInfo>& value) { next_map_ = value; } 176*eb293b8fSAndroid Build Coastguard Worker 177*eb293b8fSAndroid Build Coastguard Worker // This function guarantees it will never return nullptr. 178*eb293b8fSAndroid Build Coastguard Worker Elf* GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch); 179*eb293b8fSAndroid Build Coastguard Worker 180*eb293b8fSAndroid Build Coastguard Worker // Guaranteed to return the proper value if GetElf() has been called. 181*eb293b8fSAndroid Build Coastguard Worker uint64_t GetLoadBias(); 182*eb293b8fSAndroid Build Coastguard Worker 183*eb293b8fSAndroid Build Coastguard Worker // Will get the proper value even if GetElf() hasn't been called. 184*eb293b8fSAndroid Build Coastguard Worker uint64_t GetLoadBias(const std::shared_ptr<Memory>& process_memory); 185*eb293b8fSAndroid Build Coastguard Worker 186*eb293b8fSAndroid Build Coastguard Worker // This returns the name of the map plus the soname if this particular 187*eb293b8fSAndroid Build Coastguard Worker // map represents an elf file that is contained inside of another file. 188*eb293b8fSAndroid Build Coastguard Worker // The format of this soname embedded name is: 189*eb293b8fSAndroid Build Coastguard Worker // file.apk!libutils.so 190*eb293b8fSAndroid Build Coastguard Worker // Otherwise, this function only returns the name of the map. 191*eb293b8fSAndroid Build Coastguard Worker std::string GetFullName(); 192*eb293b8fSAndroid Build Coastguard Worker 193*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> CreateMemory(const std::shared_ptr<Memory>& process_memory); 194*eb293b8fSAndroid Build Coastguard Worker 195*eb293b8fSAndroid Build Coastguard Worker bool GetFunctionName(uint64_t addr, SharedString* name, uint64_t* func_offset); 196*eb293b8fSAndroid Build Coastguard Worker 197*eb293b8fSAndroid Build Coastguard Worker // Returns the raw build id read from the elf data. 198*eb293b8fSAndroid Build Coastguard Worker SharedString GetBuildID(); 199*eb293b8fSAndroid Build Coastguard Worker 200*eb293b8fSAndroid Build Coastguard Worker // Used internally, and by tests. It sets the value only if it was not already set. 201*eb293b8fSAndroid Build Coastguard Worker SharedString SetBuildID(std::string&& new_build_id); 202*eb293b8fSAndroid Build Coastguard Worker 203*eb293b8fSAndroid Build Coastguard Worker // Returns the printable version of the build id (hex dump of raw data). 204*eb293b8fSAndroid Build Coastguard Worker std::string GetPrintableBuildID(); 205*eb293b8fSAndroid Build Coastguard Worker 206*eb293b8fSAndroid Build Coastguard Worker // A blank map can have no name, or be a kernel named map [page size compat] 207*eb293b8fSAndroid Build Coastguard Worker // that should be skipped. IsBlank()208*eb293b8fSAndroid Build Coastguard Worker inline bool IsBlank() { 209*eb293b8fSAndroid Build Coastguard Worker return offset() == 0 && flags() == 0 && (name().empty() || name() == "[page size compat]"); 210*eb293b8fSAndroid Build Coastguard Worker } 211*eb293b8fSAndroid Build Coastguard Worker 212*eb293b8fSAndroid Build Coastguard Worker // Returns elf_fields_. It will create the object if it is null. 213*eb293b8fSAndroid Build Coastguard Worker ElfFields& GetElfFields(); 214*eb293b8fSAndroid Build Coastguard Worker 215*eb293b8fSAndroid Build Coastguard Worker private: 216*eb293b8fSAndroid Build Coastguard Worker MapInfo(const MapInfo&) = delete; 217*eb293b8fSAndroid Build Coastguard Worker void operator=(const MapInfo&) = delete; 218*eb293b8fSAndroid Build Coastguard Worker 219*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> CreateFileMemory(); 220*eb293b8fSAndroid Build Coastguard Worker bool InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory); 221*eb293b8fSAndroid Build Coastguard Worker 222*eb293b8fSAndroid Build Coastguard Worker // Protect the creation of the elf object. elf_mutex()223*eb293b8fSAndroid Build Coastguard Worker std::mutex& elf_mutex() { return GetElfFields().elf_mutex_; } 224*eb293b8fSAndroid Build Coastguard Worker 225*eb293b8fSAndroid Build Coastguard Worker uint64_t start_ = 0; 226*eb293b8fSAndroid Build Coastguard Worker uint64_t end_ = 0; 227*eb293b8fSAndroid Build Coastguard Worker uint64_t offset_ = 0; 228*eb293b8fSAndroid Build Coastguard Worker uint16_t flags_ = 0; 229*eb293b8fSAndroid Build Coastguard Worker SharedString name_; 230*eb293b8fSAndroid Build Coastguard Worker 231*eb293b8fSAndroid Build Coastguard Worker std::atomic<ElfFields*> elf_fields_; 232*eb293b8fSAndroid Build Coastguard Worker 233*eb293b8fSAndroid Build Coastguard Worker std::weak_ptr<MapInfo> prev_map_; 234*eb293b8fSAndroid Build Coastguard Worker std::weak_ptr<MapInfo> next_map_; 235*eb293b8fSAndroid Build Coastguard Worker }; 236*eb293b8fSAndroid Build Coastguard Worker 237*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack 238