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_DWARF_SECTION_H 18 #define _LIBUNWINDSTACK_DWARF_SECTION_H 19 20 #include <stdint.h> 21 22 #include <iterator> 23 #include <map> 24 #include <optional> 25 #include <unordered_map> 26 27 #include <unwindstack/DwarfError.h> 28 #include <unwindstack/DwarfLocation.h> 29 #include <unwindstack/DwarfMemory.h> 30 #include <unwindstack/DwarfStructs.h> 31 32 namespace unwindstack { 33 34 // Forward declarations. 35 enum ArchEnum : uint8_t; 36 class Memory; 37 class Regs; 38 template <typename AddressType> 39 struct RegsInfo; 40 41 class DwarfSection { 42 public: 43 DwarfSection(Memory* memory); 44 virtual ~DwarfSection() = default; 45 46 class iterator : public std::iterator<std::bidirectional_iterator_tag, DwarfFde*> { 47 public: iterator(DwarfSection * section,size_t index)48 iterator(DwarfSection* section, size_t index) : index_(index) { 49 section->GetFdes(&fdes_); 50 if (index_ == static_cast<size_t>(-1)) { 51 index_ = fdes_.size(); 52 } 53 } 54 55 iterator& operator++() { 56 index_++; 57 return *this; 58 } 59 iterator& operator++(int increment) { 60 index_ += increment; 61 return *this; 62 } 63 iterator& operator--() { 64 index_--; 65 return *this; 66 } 67 iterator& operator--(int decrement) { 68 index_ -= decrement; 69 return *this; 70 } 71 72 bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; } 73 bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; } 74 75 const DwarfFde* operator*() { 76 if (index_ > fdes_.size()) return nullptr; 77 return fdes_[index_]; 78 } 79 80 private: 81 std::vector<const DwarfFde*> fdes_; 82 size_t index_ = 0; 83 }; 84 begin()85 iterator begin() { return iterator(this, 0); } end()86 iterator end() { return iterator(this, static_cast<size_t>(-1)); } 87 LastErrorCode()88 DwarfErrorCode LastErrorCode() { return last_error_.code; } LastErrorAddress()89 uint64_t LastErrorAddress() { return last_error_.address; } 90 91 virtual bool Init(uint64_t offset, uint64_t size, int64_t section_bias) = 0; 92 93 virtual bool Eval(const DwarfCie*, Memory*, const DwarfLocations&, Regs*, bool*) = 0; 94 95 virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) = 0; 96 97 virtual void GetFdes(std::vector<const DwarfFde*>* fdes) = 0; 98 99 virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0; 100 101 virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, DwarfLocations* loc_regs, 102 ArchEnum arch) = 0; 103 104 virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0; 105 106 virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0; 107 108 virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0; 109 110 bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame); 111 112 protected: 113 DwarfMemory memory_; 114 DwarfErrorData last_error_{DWARF_ERROR_NONE, 0}; 115 116 uint32_t cie32_value_ = 0; 117 uint64_t cie64_value_ = 0; 118 119 std::unordered_map<uint64_t, DwarfFde> fde_entries_; 120 std::unordered_map<uint64_t, DwarfCie> cie_entries_; 121 std::unordered_map<uint64_t, DwarfLocations> cie_loc_regs_; 122 std::map<uint64_t, DwarfLocations> loc_regs_; // Single row indexed by pc_end. 123 }; 124 125 template <typename AddressType> 126 class DwarfSectionImpl : public DwarfSection { 127 public: DwarfSectionImpl(Memory * memory)128 DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {} 129 virtual ~DwarfSectionImpl() = default; 130 131 bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override; 132 133 const DwarfCie* GetCieFromOffset(uint64_t offset); 134 135 const DwarfFde* GetFdeFromOffset(uint64_t offset); 136 137 const DwarfFde* GetFdeFromPc(uint64_t pc) override; 138 139 void GetFdes(std::vector<const DwarfFde*>* fdes) override; 140 141 bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info); 142 143 bool Eval(const DwarfCie* cie, Memory* regular_memory, const DwarfLocations& loc_regs, Regs* regs, 144 bool* finished) override; 145 146 bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, DwarfLocations* loc_regs, 147 ArchEnum arch) override; 148 149 bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) override; 150 151 protected: 152 using DwarfFdeMap = 153 std::map</*end*/ uint64_t, std::pair</*start*/ uint64_t, /*offset*/ uint64_t>>; 154 155 bool GetNextCieOrFde(/*inout*/ uint64_t& offset, /*out*/ std::optional<DwarfFde>& fde); 156 157 bool FillInCieHeader(DwarfCie* cie); 158 159 bool FillInCie(DwarfCie* cie); 160 161 bool FillInFdeHeader(DwarfFde* fde); 162 163 bool FillInFde(DwarfFde* fde); 164 165 bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value, 166 RegsInfo<AddressType>* regs_info, bool* is_dex_pc); 167 168 static void InsertFde(uint64_t fde_offset, const DwarfFde* fde, /*out*/ DwarfFdeMap& fdes); 169 170 void BuildFdeIndex(); 171 172 int64_t section_bias_ = 0; 173 uint64_t entries_offset_ = 0; 174 uint64_t entries_end_ = 0; 175 uint64_t pc_offset_ = 0; 176 177 // Binary search table (similar to .eh_frame_hdr). Contains only FDE offsets to save memory. 178 std::vector<std::pair</*function end address*/ uint64_t, /*FDE offset*/ uint64_t>> fde_index_; 179 }; 180 181 } // namespace unwindstack 182 183 #endif // _LIBUNWINDSTACK_DWARF_SECTION_H 184