1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 #ifndef _LIBUNWINDSTACK_MAP_INFO_H 18 #define _LIBUNWINDSTACK_MAP_INFO_H 19 20 #include <stdint.h> 21 22 #include <atomic> 23 #include <memory> 24 #include <mutex> 25 #include <string> 26 27 #include <unwindstack/Elf.h> 28 #include <unwindstack/SharedString.h> 29 30 namespace unwindstack { 31 32 class MemoryFileAtOffset; 33 34 // Represents virtual memory map (as obtained from /proc/*/maps). 35 // 36 // Note that we have to be surprisingly careful with memory usage here, 37 // since in system-wide profiling this data can take considerable space. 38 // (for example, 400 process * 400 maps * 128 bytes = 20 MB + string data). 39 class MapInfo { 40 public: MapInfo(MapInfo * prev_map,MapInfo * prev_real_map,uint64_t start,uint64_t end,uint64_t offset,uint64_t flags,SharedString name)41 MapInfo(MapInfo* prev_map, MapInfo* prev_real_map, uint64_t start, uint64_t end, uint64_t offset, 42 uint64_t flags, SharedString name) 43 : start_(start), 44 end_(end), 45 offset_(offset), 46 flags_(flags), 47 name_(name), 48 elf_fields_(nullptr), 49 prev_map_(prev_map), 50 prev_real_map_(prev_real_map) { 51 if (prev_real_map != nullptr) prev_real_map->next_real_map_ = this; 52 } 53 ~MapInfo(); 54 55 // Cached data for mapped ELF files. 56 // We allocate this structure lazily since there are much fewer ELFs than maps. 57 struct ElfFields { ElfFieldsElfFields58 ElfFields() : load_bias_(INT64_MAX), build_id_(0) {} 59 60 std::shared_ptr<Elf> elf_; 61 // The offset of the beginning of this mapping to the beginning of the 62 // ELF file. 63 // elf_offset == offset - elf_start_offset. 64 // This value is only non-zero if the offset is non-zero but there is 65 // no elf signature found at that offset. 66 uint64_t elf_offset_ = 0; 67 // This value is the offset into the file of the map in memory that is the 68 // start of the elf. This is not equal to offset when the linker splits 69 // shared libraries into a read-only and read-execute map. 70 uint64_t elf_start_offset_ = 0; 71 72 std::atomic_int64_t load_bias_; 73 74 // This is a pointer to a new'd std::string. 75 // Using an atomic value means that we don't need to lock and will 76 // make it easier to move to a fine grained lock in the future. 77 std::atomic<SharedString*> build_id_; 78 79 // Set to true if the elf file data is coming from memory. 80 bool memory_backed_elf_ = false; 81 82 // Protect the creation of the elf object. 83 std::mutex elf_mutex_; 84 }; 85 start()86 inline uint64_t start() const { return start_; } set_start(uint64_t value)87 inline void set_start(uint64_t value) { start_ = value; } 88 end()89 inline uint64_t end() const { return end_; } set_end(uint64_t value)90 inline void set_end(uint64_t value) { end_ = value; } 91 offset()92 inline uint64_t offset() const { return offset_; } set_offset(uint64_t value)93 inline void set_offset(uint64_t value) { offset_ = value; } 94 flags()95 inline uint16_t flags() const { return flags_; } set_flags(uint16_t value)96 inline void set_flags(uint16_t value) { flags_ = value; } 97 name()98 inline SharedString& name() { return name_; } set_name(SharedString & value)99 inline void set_name(SharedString& value) { name_ = value; } set_name(const char * value)100 inline void set_name(const char* value) { name_ = value; } 101 elf()102 inline std::shared_ptr<Elf>& elf() { return GetElfFields().elf_; } set_elf(std::shared_ptr<Elf> & value)103 inline void set_elf(std::shared_ptr<Elf>& value) { GetElfFields().elf_ = value; } set_elf(Elf * value)104 inline void set_elf(Elf* value) { GetElfFields().elf_.reset(value); } 105 elf_offset()106 inline uint64_t elf_offset() { return GetElfFields().elf_offset_; } set_elf_offset(uint64_t value)107 inline void set_elf_offset(uint64_t value) { GetElfFields().elf_offset_ = value; } 108 elf_start_offset()109 inline uint64_t elf_start_offset() { return GetElfFields().elf_start_offset_; } set_elf_start_offset(uint64_t value)110 inline void set_elf_start_offset(uint64_t value) { GetElfFields().elf_start_offset_ = value; } 111 load_bias()112 inline std::atomic_int64_t& load_bias() { return GetElfFields().load_bias_; } set_load_bias(int64_t value)113 inline void set_load_bias(int64_t value) { GetElfFields().load_bias_ = value; } 114 build_id()115 inline std::atomic<SharedString*>& build_id() { return GetElfFields().build_id_; } set_build_id(SharedString * value)116 inline void set_build_id(SharedString* value) { GetElfFields().build_id_ = value; } 117 memory_backed_elf()118 inline bool memory_backed_elf() { return GetElfFields().memory_backed_elf_; } set_memory_backed_elf(bool value)119 inline void set_memory_backed_elf(bool value) { GetElfFields().memory_backed_elf_ = value; } 120 prev_map()121 inline MapInfo* prev_map() const { return prev_map_; } set_prev_map(MapInfo * value)122 inline void set_prev_map(MapInfo* value) { prev_map_ = value; } 123 prev_real_map()124 inline MapInfo* prev_real_map() const { return prev_real_map_; } set_prev_real_map(MapInfo * value)125 inline void set_prev_real_map(MapInfo* value) { prev_real_map_ = value; } 126 next_real_map()127 inline MapInfo* next_real_map() const { return next_real_map_; } set_next_real_map(MapInfo * value)128 inline void set_next_real_map(MapInfo* value) { next_real_map_ = value; } 129 130 // This function guarantees it will never return nullptr. 131 Elf* GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch); 132 133 uint64_t GetLoadBias(const std::shared_ptr<Memory>& process_memory); 134 135 Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory); 136 137 bool GetFunctionName(uint64_t addr, SharedString* name, uint64_t* func_offset); 138 139 // Returns the raw build id read from the elf data. 140 SharedString GetBuildID(); 141 142 // Used internally, and by tests. It sets the value only if it was not already set. 143 SharedString SetBuildID(std::string&& new_build_id); 144 145 // Returns the printable version of the build id (hex dump of raw data). 146 std::string GetPrintableBuildID(); 147 IsBlank()148 inline bool IsBlank() { return offset() == 0 && flags() == 0 && name().empty(); } 149 150 // Returns elf_fields_. It will create the object if it is null. 151 ElfFields& GetElfFields(); 152 153 private: 154 MapInfo(const MapInfo&) = delete; 155 void operator=(const MapInfo&) = delete; 156 157 Memory* GetFileMemory(); 158 bool InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory); 159 160 // Protect the creation of the elf object. elf_mutex()161 std::mutex& elf_mutex() { return GetElfFields().elf_mutex_; } 162 163 uint64_t start_ = 0; 164 uint64_t end_ = 0; 165 uint64_t offset_ = 0; 166 uint16_t flags_ = 0; 167 SharedString name_; 168 169 std::atomic<ElfFields*> elf_fields_; 170 171 MapInfo* prev_map_ = nullptr; 172 // This is the previous map that is not empty with a 0 offset. For 173 // example, this set of maps: 174 // 1000-2000 r--p 000000 00:00 0 libc.so 175 // 2000-3000 ---p 000000 00:00 0 libc.so 176 // 3000-4000 r-xp 003000 00:00 0 libc.so 177 // The last map's prev_map would point to the 2000-3000 map, while the 178 // prev_real_map would point to the 1000-2000 map. 179 MapInfo* prev_real_map_ = nullptr; 180 181 // Same as above but set to point to the next map. 182 MapInfo* next_real_map_ = nullptr; 183 }; 184 185 } // namespace unwindstack 186 187 #endif // _LIBUNWINDSTACK_MAP_INFO_H 188