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