xref: /aosp_15_r20/system/unwinding/libunwindstack/include/unwindstack/DwarfSection.h (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
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