xref: /aosp_15_r20/system/unwinding/libunwindstack/DwarfSection.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2017 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 #include <stdint.h>
18*eb293b8fSAndroid Build Coastguard Worker 
19*eb293b8fSAndroid Build Coastguard Worker #include <algorithm>
20*eb293b8fSAndroid Build Coastguard Worker #include <optional>
21*eb293b8fSAndroid Build Coastguard Worker #include <tuple>
22*eb293b8fSAndroid Build Coastguard Worker #include <utility>
23*eb293b8fSAndroid Build Coastguard Worker #include <vector>
24*eb293b8fSAndroid Build Coastguard Worker 
25*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfError.h>
26*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfLocation.h>
27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfMemory.h>
28*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfSection.h>
29*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfStructs.h>
30*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
31*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Log.h>
32*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
33*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Regs.h>
34*eb293b8fSAndroid Build Coastguard Worker 
35*eb293b8fSAndroid Build Coastguard Worker #include "DwarfCfa.h"
36*eb293b8fSAndroid Build Coastguard Worker #include "DwarfDebugFrame.h"
37*eb293b8fSAndroid Build Coastguard Worker #include "DwarfEhFrame.h"
38*eb293b8fSAndroid Build Coastguard Worker #include "DwarfEncoding.h"
39*eb293b8fSAndroid Build Coastguard Worker #include "DwarfOp.h"
40*eb293b8fSAndroid Build Coastguard Worker #include "RegsInfo.h"
41*eb293b8fSAndroid Build Coastguard Worker 
42*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
43*eb293b8fSAndroid Build Coastguard Worker 
DwarfSection(std::shared_ptr<Memory> & memory)44*eb293b8fSAndroid Build Coastguard Worker DwarfSection::DwarfSection(std::shared_ptr<Memory>& memory) : memory_(memory) {}
45*eb293b8fSAndroid Build Coastguard Worker 
Step(uint64_t pc,Regs * regs,Memory * process_memory,bool * finished,bool * is_signal_frame)46*eb293b8fSAndroid Build Coastguard Worker bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished,
47*eb293b8fSAndroid Build Coastguard Worker                         bool* is_signal_frame) {
48*eb293b8fSAndroid Build Coastguard Worker   // Lookup the pc in the cache.
49*eb293b8fSAndroid Build Coastguard Worker   auto it = loc_regs_.upper_bound(pc);
50*eb293b8fSAndroid Build Coastguard Worker   if (it == loc_regs_.end() || pc < it->second.pc_start) {
51*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_NONE;
52*eb293b8fSAndroid Build Coastguard Worker     const DwarfFde* fde = GetFdeFromPc(pc);
53*eb293b8fSAndroid Build Coastguard Worker     if (fde == nullptr || fde->cie == nullptr) {
54*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
55*eb293b8fSAndroid Build Coastguard Worker       return false;
56*eb293b8fSAndroid Build Coastguard Worker     }
57*eb293b8fSAndroid Build Coastguard Worker 
58*eb293b8fSAndroid Build Coastguard Worker     // Now get the location information for this pc.
59*eb293b8fSAndroid Build Coastguard Worker     DwarfLocations loc_regs;
60*eb293b8fSAndroid Build Coastguard Worker     if (!GetCfaLocationInfo(pc, fde, &loc_regs, regs->Arch())) {
61*eb293b8fSAndroid Build Coastguard Worker       return false;
62*eb293b8fSAndroid Build Coastguard Worker     }
63*eb293b8fSAndroid Build Coastguard Worker     loc_regs.cie = fde->cie;
64*eb293b8fSAndroid Build Coastguard Worker 
65*eb293b8fSAndroid Build Coastguard Worker     // Store it in the cache.
66*eb293b8fSAndroid Build Coastguard Worker     it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first;
67*eb293b8fSAndroid Build Coastguard Worker   }
68*eb293b8fSAndroid Build Coastguard Worker 
69*eb293b8fSAndroid Build Coastguard Worker   *is_signal_frame = it->second.cie->is_signal_frame;
70*eb293b8fSAndroid Build Coastguard Worker 
71*eb293b8fSAndroid Build Coastguard Worker   // Now eval the actual registers.
72*eb293b8fSAndroid Build Coastguard Worker   return Eval(it->second.cie, process_memory, it->second, regs, finished);
73*eb293b8fSAndroid Build Coastguard Worker }
74*eb293b8fSAndroid Build Coastguard Worker 
75*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
GetCieFromOffset(uint64_t offset)76*eb293b8fSAndroid Build Coastguard Worker const DwarfCie* DwarfSectionImpl<AddressType>::GetCieFromOffset(uint64_t offset) {
77*eb293b8fSAndroid Build Coastguard Worker   auto cie_entry = cie_entries_.find(offset);
78*eb293b8fSAndroid Build Coastguard Worker   if (cie_entry != cie_entries_.end()) {
79*eb293b8fSAndroid Build Coastguard Worker     return &cie_entry->second;
80*eb293b8fSAndroid Build Coastguard Worker   }
81*eb293b8fSAndroid Build Coastguard Worker   DwarfCie* cie = &cie_entries_[offset];
82*eb293b8fSAndroid Build Coastguard Worker   memory_.set_data_offset(entries_offset_);
83*eb293b8fSAndroid Build Coastguard Worker   memory_.set_cur_offset(offset);
84*eb293b8fSAndroid Build Coastguard Worker   if (!FillInCieHeader(cie) || !FillInCie(cie)) {
85*eb293b8fSAndroid Build Coastguard Worker     // Erase the cached entry.
86*eb293b8fSAndroid Build Coastguard Worker     cie_entries_.erase(offset);
87*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
88*eb293b8fSAndroid Build Coastguard Worker   }
89*eb293b8fSAndroid Build Coastguard Worker   return cie;
90*eb293b8fSAndroid Build Coastguard Worker }
91*eb293b8fSAndroid Build Coastguard Worker 
92*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
FillInCieHeader(DwarfCie * cie)93*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::FillInCieHeader(DwarfCie* cie) {
94*eb293b8fSAndroid Build Coastguard Worker   cie->lsda_encoding = DW_EH_PE_omit;
95*eb293b8fSAndroid Build Coastguard Worker   uint32_t length32;
96*eb293b8fSAndroid Build Coastguard Worker   if (!memory_.ReadBytes(&length32, sizeof(length32))) {
97*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
98*eb293b8fSAndroid Build Coastguard Worker     last_error_.address = memory_.cur_offset();
99*eb293b8fSAndroid Build Coastguard Worker     return false;
100*eb293b8fSAndroid Build Coastguard Worker   }
101*eb293b8fSAndroid Build Coastguard Worker   if (length32 == static_cast<uint32_t>(-1)) {
102*eb293b8fSAndroid Build Coastguard Worker     // 64 bit Cie
103*eb293b8fSAndroid Build Coastguard Worker     uint64_t length64;
104*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&length64, sizeof(length64))) {
105*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
106*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
107*eb293b8fSAndroid Build Coastguard Worker       return false;
108*eb293b8fSAndroid Build Coastguard Worker     }
109*eb293b8fSAndroid Build Coastguard Worker 
110*eb293b8fSAndroid Build Coastguard Worker     cie->cfa_instructions_end = memory_.cur_offset() + length64;
111*eb293b8fSAndroid Build Coastguard Worker     // TODO(b/192012848): This is wrong. We need to propagate pointer size here.
112*eb293b8fSAndroid Build Coastguard Worker     cie->fde_address_encoding = DW_EH_PE_udata8;
113*eb293b8fSAndroid Build Coastguard Worker 
114*eb293b8fSAndroid Build Coastguard Worker     uint64_t cie_id;
115*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
116*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
117*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
118*eb293b8fSAndroid Build Coastguard Worker       return false;
119*eb293b8fSAndroid Build Coastguard Worker     }
120*eb293b8fSAndroid Build Coastguard Worker     if (cie_id != cie64_value_) {
121*eb293b8fSAndroid Build Coastguard Worker       // This is not a Cie, something has gone horribly wrong.
122*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
123*eb293b8fSAndroid Build Coastguard Worker       return false;
124*eb293b8fSAndroid Build Coastguard Worker     }
125*eb293b8fSAndroid Build Coastguard Worker   } else {
126*eb293b8fSAndroid Build Coastguard Worker     // 32 bit Cie
127*eb293b8fSAndroid Build Coastguard Worker     cie->cfa_instructions_end = memory_.cur_offset() + length32;
128*eb293b8fSAndroid Build Coastguard Worker     // TODO(b/192012848): This is wrong. We need to propagate pointer size here.
129*eb293b8fSAndroid Build Coastguard Worker     cie->fde_address_encoding = DW_EH_PE_udata4;
130*eb293b8fSAndroid Build Coastguard Worker 
131*eb293b8fSAndroid Build Coastguard Worker     uint32_t cie_id;
132*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
133*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
134*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
135*eb293b8fSAndroid Build Coastguard Worker       return false;
136*eb293b8fSAndroid Build Coastguard Worker     }
137*eb293b8fSAndroid Build Coastguard Worker     if (cie_id != cie32_value_) {
138*eb293b8fSAndroid Build Coastguard Worker       // This is not a Cie, something has gone horribly wrong.
139*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
140*eb293b8fSAndroid Build Coastguard Worker       return false;
141*eb293b8fSAndroid Build Coastguard Worker     }
142*eb293b8fSAndroid Build Coastguard Worker   }
143*eb293b8fSAndroid Build Coastguard Worker   return true;
144*eb293b8fSAndroid Build Coastguard Worker }
145*eb293b8fSAndroid Build Coastguard Worker 
146*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
FillInCie(DwarfCie * cie)147*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
148*eb293b8fSAndroid Build Coastguard Worker   if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
149*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
150*eb293b8fSAndroid Build Coastguard Worker     last_error_.address = memory_.cur_offset();
151*eb293b8fSAndroid Build Coastguard Worker     return false;
152*eb293b8fSAndroid Build Coastguard Worker   }
153*eb293b8fSAndroid Build Coastguard Worker 
154*eb293b8fSAndroid Build Coastguard Worker   if (cie->version != 1 && cie->version != 3 && cie->version != 4 && cie->version != 5) {
155*eb293b8fSAndroid Build Coastguard Worker     // Unrecognized version.
156*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION;
157*eb293b8fSAndroid Build Coastguard Worker     return false;
158*eb293b8fSAndroid Build Coastguard Worker   }
159*eb293b8fSAndroid Build Coastguard Worker 
160*eb293b8fSAndroid Build Coastguard Worker   // Read the augmentation string.
161*eb293b8fSAndroid Build Coastguard Worker   char aug_value;
162*eb293b8fSAndroid Build Coastguard Worker   do {
163*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&aug_value, 1)) {
164*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
165*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
166*eb293b8fSAndroid Build Coastguard Worker       return false;
167*eb293b8fSAndroid Build Coastguard Worker     }
168*eb293b8fSAndroid Build Coastguard Worker     cie->augmentation_string.push_back(aug_value);
169*eb293b8fSAndroid Build Coastguard Worker   } while (aug_value != '\0');
170*eb293b8fSAndroid Build Coastguard Worker 
171*eb293b8fSAndroid Build Coastguard Worker   if (cie->version == 4 || cie->version == 5) {
172*eb293b8fSAndroid Build Coastguard Worker     char address_size;
173*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&address_size, 1)) {
174*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
175*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
176*eb293b8fSAndroid Build Coastguard Worker       return false;
177*eb293b8fSAndroid Build Coastguard Worker     }
178*eb293b8fSAndroid Build Coastguard Worker     cie->fde_address_encoding = address_size == 8 ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
179*eb293b8fSAndroid Build Coastguard Worker 
180*eb293b8fSAndroid Build Coastguard Worker     // Segment Size
181*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&cie->segment_size, 1)) {
182*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
183*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
184*eb293b8fSAndroid Build Coastguard Worker       return false;
185*eb293b8fSAndroid Build Coastguard Worker     }
186*eb293b8fSAndroid Build Coastguard Worker   }
187*eb293b8fSAndroid Build Coastguard Worker 
188*eb293b8fSAndroid Build Coastguard Worker   // Code Alignment Factor
189*eb293b8fSAndroid Build Coastguard Worker   if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
190*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
191*eb293b8fSAndroid Build Coastguard Worker     last_error_.address = memory_.cur_offset();
192*eb293b8fSAndroid Build Coastguard Worker     return false;
193*eb293b8fSAndroid Build Coastguard Worker   }
194*eb293b8fSAndroid Build Coastguard Worker 
195*eb293b8fSAndroid Build Coastguard Worker   // Data Alignment Factor
196*eb293b8fSAndroid Build Coastguard Worker   if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
197*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
198*eb293b8fSAndroid Build Coastguard Worker     last_error_.address = memory_.cur_offset();
199*eb293b8fSAndroid Build Coastguard Worker     return false;
200*eb293b8fSAndroid Build Coastguard Worker   }
201*eb293b8fSAndroid Build Coastguard Worker 
202*eb293b8fSAndroid Build Coastguard Worker   if (cie->version == 1) {
203*eb293b8fSAndroid Build Coastguard Worker     // Return Address is a single byte.
204*eb293b8fSAndroid Build Coastguard Worker     uint8_t return_address_register;
205*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&return_address_register, 1)) {
206*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
207*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
208*eb293b8fSAndroid Build Coastguard Worker       return false;
209*eb293b8fSAndroid Build Coastguard Worker     }
210*eb293b8fSAndroid Build Coastguard Worker     cie->return_address_register = return_address_register;
211*eb293b8fSAndroid Build Coastguard Worker   } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
212*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
213*eb293b8fSAndroid Build Coastguard Worker     last_error_.address = memory_.cur_offset();
214*eb293b8fSAndroid Build Coastguard Worker     return false;
215*eb293b8fSAndroid Build Coastguard Worker   }
216*eb293b8fSAndroid Build Coastguard Worker 
217*eb293b8fSAndroid Build Coastguard Worker   if (cie->augmentation_string[0] != 'z') {
218*eb293b8fSAndroid Build Coastguard Worker     cie->cfa_instructions_offset = memory_.cur_offset();
219*eb293b8fSAndroid Build Coastguard Worker     return true;
220*eb293b8fSAndroid Build Coastguard Worker   }
221*eb293b8fSAndroid Build Coastguard Worker 
222*eb293b8fSAndroid Build Coastguard Worker   uint64_t aug_length;
223*eb293b8fSAndroid Build Coastguard Worker   if (!memory_.ReadULEB128(&aug_length)) {
224*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
225*eb293b8fSAndroid Build Coastguard Worker     last_error_.address = memory_.cur_offset();
226*eb293b8fSAndroid Build Coastguard Worker     return false;
227*eb293b8fSAndroid Build Coastguard Worker   }
228*eb293b8fSAndroid Build Coastguard Worker   cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
229*eb293b8fSAndroid Build Coastguard Worker 
230*eb293b8fSAndroid Build Coastguard Worker   for (size_t i = 1; i < cie->augmentation_string.size(); i++) {
231*eb293b8fSAndroid Build Coastguard Worker     switch (cie->augmentation_string[i]) {
232*eb293b8fSAndroid Build Coastguard Worker       case 'L':
233*eb293b8fSAndroid Build Coastguard Worker         if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
234*eb293b8fSAndroid Build Coastguard Worker           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
235*eb293b8fSAndroid Build Coastguard Worker           last_error_.address = memory_.cur_offset();
236*eb293b8fSAndroid Build Coastguard Worker           return false;
237*eb293b8fSAndroid Build Coastguard Worker         }
238*eb293b8fSAndroid Build Coastguard Worker         break;
239*eb293b8fSAndroid Build Coastguard Worker       case 'P': {
240*eb293b8fSAndroid Build Coastguard Worker         uint8_t encoding;
241*eb293b8fSAndroid Build Coastguard Worker         if (!memory_.ReadBytes(&encoding, 1)) {
242*eb293b8fSAndroid Build Coastguard Worker           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
243*eb293b8fSAndroid Build Coastguard Worker           last_error_.address = memory_.cur_offset();
244*eb293b8fSAndroid Build Coastguard Worker           return false;
245*eb293b8fSAndroid Build Coastguard Worker         }
246*eb293b8fSAndroid Build Coastguard Worker         memory_.set_pc_offset(pc_offset_);
247*eb293b8fSAndroid Build Coastguard Worker         if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
248*eb293b8fSAndroid Build Coastguard Worker           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
249*eb293b8fSAndroid Build Coastguard Worker           last_error_.address = memory_.cur_offset();
250*eb293b8fSAndroid Build Coastguard Worker           return false;
251*eb293b8fSAndroid Build Coastguard Worker         }
252*eb293b8fSAndroid Build Coastguard Worker       } break;
253*eb293b8fSAndroid Build Coastguard Worker       case 'R':
254*eb293b8fSAndroid Build Coastguard Worker         if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
255*eb293b8fSAndroid Build Coastguard Worker           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
256*eb293b8fSAndroid Build Coastguard Worker           last_error_.address = memory_.cur_offset();
257*eb293b8fSAndroid Build Coastguard Worker           return false;
258*eb293b8fSAndroid Build Coastguard Worker         }
259*eb293b8fSAndroid Build Coastguard Worker         break;
260*eb293b8fSAndroid Build Coastguard Worker       case 'S':
261*eb293b8fSAndroid Build Coastguard Worker         cie->is_signal_frame = true;
262*eb293b8fSAndroid Build Coastguard Worker         break;
263*eb293b8fSAndroid Build Coastguard Worker     }
264*eb293b8fSAndroid Build Coastguard Worker   }
265*eb293b8fSAndroid Build Coastguard Worker   return true;
266*eb293b8fSAndroid Build Coastguard Worker }
267*eb293b8fSAndroid Build Coastguard Worker 
268*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
GetFdeFromOffset(uint64_t offset)269*eb293b8fSAndroid Build Coastguard Worker const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset) {
270*eb293b8fSAndroid Build Coastguard Worker   auto fde_entry = fde_entries_.find(offset);
271*eb293b8fSAndroid Build Coastguard Worker   if (fde_entry != fde_entries_.end()) {
272*eb293b8fSAndroid Build Coastguard Worker     return &fde_entry->second;
273*eb293b8fSAndroid Build Coastguard Worker   }
274*eb293b8fSAndroid Build Coastguard Worker   DwarfFde* fde = &fde_entries_[offset];
275*eb293b8fSAndroid Build Coastguard Worker   memory_.set_data_offset(entries_offset_);
276*eb293b8fSAndroid Build Coastguard Worker   memory_.set_cur_offset(offset);
277*eb293b8fSAndroid Build Coastguard Worker   if (!FillInFdeHeader(fde) || !FillInFde(fde)) {
278*eb293b8fSAndroid Build Coastguard Worker     fde_entries_.erase(offset);
279*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
280*eb293b8fSAndroid Build Coastguard Worker   }
281*eb293b8fSAndroid Build Coastguard Worker   return fde;
282*eb293b8fSAndroid Build Coastguard Worker }
283*eb293b8fSAndroid Build Coastguard Worker 
284*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
FillInFdeHeader(DwarfFde * fde)285*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::FillInFdeHeader(DwarfFde* fde) {
286*eb293b8fSAndroid Build Coastguard Worker   uint32_t length32;
287*eb293b8fSAndroid Build Coastguard Worker   if (!memory_.ReadBytes(&length32, sizeof(length32))) {
288*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
289*eb293b8fSAndroid Build Coastguard Worker     last_error_.address = memory_.cur_offset();
290*eb293b8fSAndroid Build Coastguard Worker     return false;
291*eb293b8fSAndroid Build Coastguard Worker   }
292*eb293b8fSAndroid Build Coastguard Worker 
293*eb293b8fSAndroid Build Coastguard Worker   if (length32 == static_cast<uint32_t>(-1)) {
294*eb293b8fSAndroid Build Coastguard Worker     // 64 bit Fde.
295*eb293b8fSAndroid Build Coastguard Worker     uint64_t length64;
296*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&length64, sizeof(length64))) {
297*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
298*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
299*eb293b8fSAndroid Build Coastguard Worker       return false;
300*eb293b8fSAndroid Build Coastguard Worker     }
301*eb293b8fSAndroid Build Coastguard Worker     fde->cfa_instructions_end = memory_.cur_offset() + length64;
302*eb293b8fSAndroid Build Coastguard Worker 
303*eb293b8fSAndroid Build Coastguard Worker     uint64_t value64;
304*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&value64, sizeof(value64))) {
305*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
306*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
307*eb293b8fSAndroid Build Coastguard Worker       return false;
308*eb293b8fSAndroid Build Coastguard Worker     }
309*eb293b8fSAndroid Build Coastguard Worker     if (value64 == cie64_value_) {
310*eb293b8fSAndroid Build Coastguard Worker       // This is a Cie, this means something has gone wrong.
311*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
312*eb293b8fSAndroid Build Coastguard Worker       return false;
313*eb293b8fSAndroid Build Coastguard Worker     }
314*eb293b8fSAndroid Build Coastguard Worker 
315*eb293b8fSAndroid Build Coastguard Worker     // Get the Cie pointer, which is necessary to properly read the rest of
316*eb293b8fSAndroid Build Coastguard Worker     // of the Fde information.
317*eb293b8fSAndroid Build Coastguard Worker     fde->cie_offset = GetCieOffsetFromFde64(value64);
318*eb293b8fSAndroid Build Coastguard Worker   } else {
319*eb293b8fSAndroid Build Coastguard Worker     // 32 bit Fde.
320*eb293b8fSAndroid Build Coastguard Worker     fde->cfa_instructions_end = memory_.cur_offset() + length32;
321*eb293b8fSAndroid Build Coastguard Worker 
322*eb293b8fSAndroid Build Coastguard Worker     uint32_t value32;
323*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&value32, sizeof(value32))) {
324*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
325*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
326*eb293b8fSAndroid Build Coastguard Worker       return false;
327*eb293b8fSAndroid Build Coastguard Worker     }
328*eb293b8fSAndroid Build Coastguard Worker     if (value32 == cie32_value_) {
329*eb293b8fSAndroid Build Coastguard Worker       // This is a Cie, this means something has gone wrong.
330*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
331*eb293b8fSAndroid Build Coastguard Worker       return false;
332*eb293b8fSAndroid Build Coastguard Worker     }
333*eb293b8fSAndroid Build Coastguard Worker 
334*eb293b8fSAndroid Build Coastguard Worker     // Get the Cie pointer, which is necessary to properly read the rest of
335*eb293b8fSAndroid Build Coastguard Worker     // of the Fde information.
336*eb293b8fSAndroid Build Coastguard Worker     fde->cie_offset = GetCieOffsetFromFde32(value32);
337*eb293b8fSAndroid Build Coastguard Worker   }
338*eb293b8fSAndroid Build Coastguard Worker   return true;
339*eb293b8fSAndroid Build Coastguard Worker }
340*eb293b8fSAndroid Build Coastguard Worker 
341*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
FillInFde(DwarfFde * fde)342*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
343*eb293b8fSAndroid Build Coastguard Worker   uint64_t cur_offset = memory_.cur_offset();
344*eb293b8fSAndroid Build Coastguard Worker 
345*eb293b8fSAndroid Build Coastguard Worker   const DwarfCie* cie = GetCieFromOffset(fde->cie_offset);
346*eb293b8fSAndroid Build Coastguard Worker   if (cie == nullptr) {
347*eb293b8fSAndroid Build Coastguard Worker     return false;
348*eb293b8fSAndroid Build Coastguard Worker   }
349*eb293b8fSAndroid Build Coastguard Worker   fde->cie = cie;
350*eb293b8fSAndroid Build Coastguard Worker 
351*eb293b8fSAndroid Build Coastguard Worker   if (cie->segment_size != 0) {
352*eb293b8fSAndroid Build Coastguard Worker     // Skip over the segment selector for now.
353*eb293b8fSAndroid Build Coastguard Worker     cur_offset += cie->segment_size;
354*eb293b8fSAndroid Build Coastguard Worker   }
355*eb293b8fSAndroid Build Coastguard Worker   memory_.set_cur_offset(cur_offset);
356*eb293b8fSAndroid Build Coastguard Worker 
357*eb293b8fSAndroid Build Coastguard Worker   // The load bias only applies to the start.
358*eb293b8fSAndroid Build Coastguard Worker   memory_.set_pc_offset(section_bias_);
359*eb293b8fSAndroid Build Coastguard Worker   bool valid = memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_start);
360*eb293b8fSAndroid Build Coastguard Worker   fde->pc_start = AdjustPcFromFde(fde->pc_start);
361*eb293b8fSAndroid Build Coastguard Worker 
362*eb293b8fSAndroid Build Coastguard Worker   memory_.set_pc_offset(0);
363*eb293b8fSAndroid Build Coastguard Worker   if (!valid || !memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_end)) {
364*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
365*eb293b8fSAndroid Build Coastguard Worker     last_error_.address = memory_.cur_offset();
366*eb293b8fSAndroid Build Coastguard Worker     return false;
367*eb293b8fSAndroid Build Coastguard Worker   }
368*eb293b8fSAndroid Build Coastguard Worker   fde->pc_end += fde->pc_start;
369*eb293b8fSAndroid Build Coastguard Worker 
370*eb293b8fSAndroid Build Coastguard Worker   if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
371*eb293b8fSAndroid Build Coastguard Worker     // Augmentation Size
372*eb293b8fSAndroid Build Coastguard Worker     uint64_t aug_length;
373*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadULEB128(&aug_length)) {
374*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
375*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
376*eb293b8fSAndroid Build Coastguard Worker       return false;
377*eb293b8fSAndroid Build Coastguard Worker     }
378*eb293b8fSAndroid Build Coastguard Worker     uint64_t cur_offset = memory_.cur_offset();
379*eb293b8fSAndroid Build Coastguard Worker 
380*eb293b8fSAndroid Build Coastguard Worker     memory_.set_pc_offset(pc_offset_);
381*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
382*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
383*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
384*eb293b8fSAndroid Build Coastguard Worker       return false;
385*eb293b8fSAndroid Build Coastguard Worker     }
386*eb293b8fSAndroid Build Coastguard Worker 
387*eb293b8fSAndroid Build Coastguard Worker     // Set our position to after all of the augmentation data.
388*eb293b8fSAndroid Build Coastguard Worker     memory_.set_cur_offset(cur_offset + aug_length);
389*eb293b8fSAndroid Build Coastguard Worker   }
390*eb293b8fSAndroid Build Coastguard Worker   fde->cfa_instructions_offset = memory_.cur_offset();
391*eb293b8fSAndroid Build Coastguard Worker 
392*eb293b8fSAndroid Build Coastguard Worker   return true;
393*eb293b8fSAndroid Build Coastguard Worker }
394*eb293b8fSAndroid Build Coastguard Worker 
395*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
EvalExpression(const DwarfLocation & loc,Memory * regular_memory,AddressType * value,RegsInfo<AddressType> * regs_info,bool * is_dex_pc)396*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory,
397*eb293b8fSAndroid Build Coastguard Worker                                                    AddressType* value,
398*eb293b8fSAndroid Build Coastguard Worker                                                    RegsInfo<AddressType>* regs_info,
399*eb293b8fSAndroid Build Coastguard Worker                                                    bool* is_dex_pc) {
400*eb293b8fSAndroid Build Coastguard Worker   DwarfOp<AddressType> op(&memory_, regular_memory);
401*eb293b8fSAndroid Build Coastguard Worker   op.set_regs_info(regs_info);
402*eb293b8fSAndroid Build Coastguard Worker 
403*eb293b8fSAndroid Build Coastguard Worker   // Need to evaluate the op data.
404*eb293b8fSAndroid Build Coastguard Worker   uint64_t end = loc.values[1];
405*eb293b8fSAndroid Build Coastguard Worker   uint64_t start = end - loc.values[0];
406*eb293b8fSAndroid Build Coastguard Worker   if (!op.Eval(start, end)) {
407*eb293b8fSAndroid Build Coastguard Worker     last_error_ = op.last_error();
408*eb293b8fSAndroid Build Coastguard Worker     return false;
409*eb293b8fSAndroid Build Coastguard Worker   }
410*eb293b8fSAndroid Build Coastguard Worker   if (op.StackSize() == 0) {
411*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
412*eb293b8fSAndroid Build Coastguard Worker     return false;
413*eb293b8fSAndroid Build Coastguard Worker   }
414*eb293b8fSAndroid Build Coastguard Worker   // We don't support an expression that evaluates to a register number.
415*eb293b8fSAndroid Build Coastguard Worker   if (op.is_register()) {
416*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
417*eb293b8fSAndroid Build Coastguard Worker     return false;
418*eb293b8fSAndroid Build Coastguard Worker   }
419*eb293b8fSAndroid Build Coastguard Worker   *value = op.StackAt(0);
420*eb293b8fSAndroid Build Coastguard Worker   if (is_dex_pc != nullptr && op.dex_pc_set()) {
421*eb293b8fSAndroid Build Coastguard Worker     *is_dex_pc = true;
422*eb293b8fSAndroid Build Coastguard Worker   }
423*eb293b8fSAndroid Build Coastguard Worker   return true;
424*eb293b8fSAndroid Build Coastguard Worker }
425*eb293b8fSAndroid Build Coastguard Worker 
426*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
427*eb293b8fSAndroid Build Coastguard Worker struct EvalInfo {
428*eb293b8fSAndroid Build Coastguard Worker   const DwarfLocations* loc_regs;
429*eb293b8fSAndroid Build Coastguard Worker   const DwarfCie* cie;
430*eb293b8fSAndroid Build Coastguard Worker   Memory* regular_memory;
431*eb293b8fSAndroid Build Coastguard Worker   AddressType cfa;
432*eb293b8fSAndroid Build Coastguard Worker   bool return_address_undefined = false;
433*eb293b8fSAndroid Build Coastguard Worker   RegsInfo<AddressType> regs_info;
434*eb293b8fSAndroid Build Coastguard Worker };
435*eb293b8fSAndroid Build Coastguard Worker 
436*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
EvalRegister(const DwarfLocation * loc,uint32_t reg,AddressType * reg_ptr,void * info)437*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg,
438*eb293b8fSAndroid Build Coastguard Worker                                                  AddressType* reg_ptr, void* info) {
439*eb293b8fSAndroid Build Coastguard Worker   EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info);
440*eb293b8fSAndroid Build Coastguard Worker   Memory* regular_memory = eval_info->regular_memory;
441*eb293b8fSAndroid Build Coastguard Worker   switch (loc->type) {
442*eb293b8fSAndroid Build Coastguard Worker     case DWARF_LOCATION_OFFSET:
443*eb293b8fSAndroid Build Coastguard Worker       if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
444*eb293b8fSAndroid Build Coastguard Worker         last_error_.code = DWARF_ERROR_MEMORY_INVALID;
445*eb293b8fSAndroid Build Coastguard Worker         last_error_.address = eval_info->cfa + loc->values[0];
446*eb293b8fSAndroid Build Coastguard Worker         return false;
447*eb293b8fSAndroid Build Coastguard Worker       }
448*eb293b8fSAndroid Build Coastguard Worker       break;
449*eb293b8fSAndroid Build Coastguard Worker     case DWARF_LOCATION_VAL_OFFSET:
450*eb293b8fSAndroid Build Coastguard Worker       *reg_ptr = eval_info->cfa + loc->values[0];
451*eb293b8fSAndroid Build Coastguard Worker       break;
452*eb293b8fSAndroid Build Coastguard Worker     case DWARF_LOCATION_REGISTER: {
453*eb293b8fSAndroid Build Coastguard Worker       uint16_t cur_reg = eval_info->regs_info.regs->Convert(loc->values[0]);
454*eb293b8fSAndroid Build Coastguard Worker       if (cur_reg >= eval_info->regs_info.Total()) {
455*eb293b8fSAndroid Build Coastguard Worker         last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
456*eb293b8fSAndroid Build Coastguard Worker         return false;
457*eb293b8fSAndroid Build Coastguard Worker       }
458*eb293b8fSAndroid Build Coastguard Worker       *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1];
459*eb293b8fSAndroid Build Coastguard Worker       break;
460*eb293b8fSAndroid Build Coastguard Worker     }
461*eb293b8fSAndroid Build Coastguard Worker     case DWARF_LOCATION_EXPRESSION:
462*eb293b8fSAndroid Build Coastguard Worker     case DWARF_LOCATION_VAL_EXPRESSION: {
463*eb293b8fSAndroid Build Coastguard Worker       AddressType value;
464*eb293b8fSAndroid Build Coastguard Worker       bool is_dex_pc = false;
465*eb293b8fSAndroid Build Coastguard Worker       if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) {
466*eb293b8fSAndroid Build Coastguard Worker         return false;
467*eb293b8fSAndroid Build Coastguard Worker       }
468*eb293b8fSAndroid Build Coastguard Worker       if (loc->type == DWARF_LOCATION_EXPRESSION) {
469*eb293b8fSAndroid Build Coastguard Worker         if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
470*eb293b8fSAndroid Build Coastguard Worker           last_error_.code = DWARF_ERROR_MEMORY_INVALID;
471*eb293b8fSAndroid Build Coastguard Worker           last_error_.address = value;
472*eb293b8fSAndroid Build Coastguard Worker           return false;
473*eb293b8fSAndroid Build Coastguard Worker         }
474*eb293b8fSAndroid Build Coastguard Worker       } else {
475*eb293b8fSAndroid Build Coastguard Worker         *reg_ptr = value;
476*eb293b8fSAndroid Build Coastguard Worker         if (is_dex_pc) {
477*eb293b8fSAndroid Build Coastguard Worker           eval_info->regs_info.regs->set_dex_pc(value);
478*eb293b8fSAndroid Build Coastguard Worker         }
479*eb293b8fSAndroid Build Coastguard Worker       }
480*eb293b8fSAndroid Build Coastguard Worker       break;
481*eb293b8fSAndroid Build Coastguard Worker     }
482*eb293b8fSAndroid Build Coastguard Worker     case DWARF_LOCATION_UNDEFINED:
483*eb293b8fSAndroid Build Coastguard Worker       if (reg == eval_info->cie->return_address_register) {
484*eb293b8fSAndroid Build Coastguard Worker         eval_info->return_address_undefined = true;
485*eb293b8fSAndroid Build Coastguard Worker       }
486*eb293b8fSAndroid Build Coastguard Worker       break;
487*eb293b8fSAndroid Build Coastguard Worker     case DWARF_LOCATION_PSEUDO_REGISTER:
488*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
489*eb293b8fSAndroid Build Coastguard Worker       return false;
490*eb293b8fSAndroid Build Coastguard Worker     default:
491*eb293b8fSAndroid Build Coastguard Worker       break;
492*eb293b8fSAndroid Build Coastguard Worker   }
493*eb293b8fSAndroid Build Coastguard Worker 
494*eb293b8fSAndroid Build Coastguard Worker   return true;
495*eb293b8fSAndroid Build Coastguard Worker }
496*eb293b8fSAndroid Build Coastguard Worker 
497*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
Eval(const DwarfCie * cie,Memory * regular_memory,const DwarfLocations & loc_regs,Regs * regs,bool * finished)498*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
499*eb293b8fSAndroid Build Coastguard Worker                                          const DwarfLocations& loc_regs, Regs* regs,
500*eb293b8fSAndroid Build Coastguard Worker                                          bool* finished) {
501*eb293b8fSAndroid Build Coastguard Worker   RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
502*eb293b8fSAndroid Build Coastguard Worker   if (cie->return_address_register >= cur_regs->total_regs()) {
503*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
504*eb293b8fSAndroid Build Coastguard Worker     return false;
505*eb293b8fSAndroid Build Coastguard Worker   }
506*eb293b8fSAndroid Build Coastguard Worker 
507*eb293b8fSAndroid Build Coastguard Worker   // Get the cfa value;
508*eb293b8fSAndroid Build Coastguard Worker   auto cfa_entry = loc_regs.find(CFA_REG);
509*eb293b8fSAndroid Build Coastguard Worker   if (cfa_entry == loc_regs.end()) {
510*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED;
511*eb293b8fSAndroid Build Coastguard Worker     return false;
512*eb293b8fSAndroid Build Coastguard Worker   }
513*eb293b8fSAndroid Build Coastguard Worker 
514*eb293b8fSAndroid Build Coastguard Worker   // Always set the dex pc to zero when evaluating.
515*eb293b8fSAndroid Build Coastguard Worker   cur_regs->set_dex_pc(0);
516*eb293b8fSAndroid Build Coastguard Worker 
517*eb293b8fSAndroid Build Coastguard Worker   // Reset necessary pseudo registers before evaluation.
518*eb293b8fSAndroid Build Coastguard Worker   // This is needed for ARM64, for example.
519*eb293b8fSAndroid Build Coastguard Worker   regs->ResetPseudoRegisters();
520*eb293b8fSAndroid Build Coastguard Worker 
521*eb293b8fSAndroid Build Coastguard Worker   EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
522*eb293b8fSAndroid Build Coastguard Worker                                   .cie = cie,
523*eb293b8fSAndroid Build Coastguard Worker                                   .regular_memory = regular_memory,
524*eb293b8fSAndroid Build Coastguard Worker                                   .regs_info = RegsInfo<AddressType>(cur_regs)};
525*eb293b8fSAndroid Build Coastguard Worker   const DwarfLocation* loc = &cfa_entry->second;
526*eb293b8fSAndroid Build Coastguard Worker   // Only a few location types are valid for the cfa.
527*eb293b8fSAndroid Build Coastguard Worker   switch (loc->type) {
528*eb293b8fSAndroid Build Coastguard Worker     case DWARF_LOCATION_REGISTER:
529*eb293b8fSAndroid Build Coastguard Worker       if (loc->values[0] >= cur_regs->total_regs()) {
530*eb293b8fSAndroid Build Coastguard Worker         last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
531*eb293b8fSAndroid Build Coastguard Worker         return false;
532*eb293b8fSAndroid Build Coastguard Worker       }
533*eb293b8fSAndroid Build Coastguard Worker       eval_info.cfa = (*cur_regs)[loc->values[0]];
534*eb293b8fSAndroid Build Coastguard Worker       eval_info.cfa += loc->values[1];
535*eb293b8fSAndroid Build Coastguard Worker       break;
536*eb293b8fSAndroid Build Coastguard Worker     case DWARF_LOCATION_VAL_EXPRESSION: {
537*eb293b8fSAndroid Build Coastguard Worker       AddressType value;
538*eb293b8fSAndroid Build Coastguard Worker       if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) {
539*eb293b8fSAndroid Build Coastguard Worker         return false;
540*eb293b8fSAndroid Build Coastguard Worker       }
541*eb293b8fSAndroid Build Coastguard Worker       // There is only one type of valid expression for CFA evaluation.
542*eb293b8fSAndroid Build Coastguard Worker       eval_info.cfa = value;
543*eb293b8fSAndroid Build Coastguard Worker       break;
544*eb293b8fSAndroid Build Coastguard Worker     }
545*eb293b8fSAndroid Build Coastguard Worker     default:
546*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
547*eb293b8fSAndroid Build Coastguard Worker       return false;
548*eb293b8fSAndroid Build Coastguard Worker   }
549*eb293b8fSAndroid Build Coastguard Worker 
550*eb293b8fSAndroid Build Coastguard Worker   for (const auto& entry : loc_regs) {
551*eb293b8fSAndroid Build Coastguard Worker     uint32_t reg = entry.first;
552*eb293b8fSAndroid Build Coastguard Worker     // Already handled the CFA register.
553*eb293b8fSAndroid Build Coastguard Worker     if (reg == CFA_REG) continue;
554*eb293b8fSAndroid Build Coastguard Worker 
555*eb293b8fSAndroid Build Coastguard Worker     AddressType* reg_ptr;
556*eb293b8fSAndroid Build Coastguard Worker     if (reg >= cur_regs->total_regs()) {
557*eb293b8fSAndroid Build Coastguard Worker       if (entry.second.type != DWARF_LOCATION_PSEUDO_REGISTER) {
558*eb293b8fSAndroid Build Coastguard Worker         // Skip this unknown register.
559*eb293b8fSAndroid Build Coastguard Worker         continue;
560*eb293b8fSAndroid Build Coastguard Worker       }
561*eb293b8fSAndroid Build Coastguard Worker       if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) {
562*eb293b8fSAndroid Build Coastguard Worker         last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
563*eb293b8fSAndroid Build Coastguard Worker         return false;
564*eb293b8fSAndroid Build Coastguard Worker       }
565*eb293b8fSAndroid Build Coastguard Worker     } else {
566*eb293b8fSAndroid Build Coastguard Worker       reg_ptr = eval_info.regs_info.Save(reg);
567*eb293b8fSAndroid Build Coastguard Worker       if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
568*eb293b8fSAndroid Build Coastguard Worker         return false;
569*eb293b8fSAndroid Build Coastguard Worker       }
570*eb293b8fSAndroid Build Coastguard Worker     }
571*eb293b8fSAndroid Build Coastguard Worker   }
572*eb293b8fSAndroid Build Coastguard Worker 
573*eb293b8fSAndroid Build Coastguard Worker   // Find the return address location.
574*eb293b8fSAndroid Build Coastguard Worker   if (eval_info.return_address_undefined) {
575*eb293b8fSAndroid Build Coastguard Worker     cur_regs->set_pc(0);
576*eb293b8fSAndroid Build Coastguard Worker   } else {
577*eb293b8fSAndroid Build Coastguard Worker     cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
578*eb293b8fSAndroid Build Coastguard Worker   }
579*eb293b8fSAndroid Build Coastguard Worker 
580*eb293b8fSAndroid Build Coastguard Worker   // If the pc was set to zero, consider this the final frame. Exception: if
581*eb293b8fSAndroid Build Coastguard Worker   // this is the sigreturn frame, then we want to try to recover the real PC
582*eb293b8fSAndroid Build Coastguard Worker   // using the return address (from LR or the stack), so keep going.
583*eb293b8fSAndroid Build Coastguard Worker   *finished = (cur_regs->pc() == 0 && !cie->is_signal_frame) ? true : false;
584*eb293b8fSAndroid Build Coastguard Worker 
585*eb293b8fSAndroid Build Coastguard Worker   cur_regs->set_sp(eval_info.cfa);
586*eb293b8fSAndroid Build Coastguard Worker 
587*eb293b8fSAndroid Build Coastguard Worker   return true;
588*eb293b8fSAndroid Build Coastguard Worker }
589*eb293b8fSAndroid Build Coastguard Worker 
590*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
GetCfaLocationInfo(uint64_t pc,const DwarfFde * fde,DwarfLocations * loc_regs,ArchEnum arch)591*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
592*eb293b8fSAndroid Build Coastguard Worker                                                        DwarfLocations* loc_regs, ArchEnum arch) {
593*eb293b8fSAndroid Build Coastguard Worker   DwarfCfa<AddressType> cfa(&memory_, fde, arch);
594*eb293b8fSAndroid Build Coastguard Worker 
595*eb293b8fSAndroid Build Coastguard Worker   // Look for the cached copy of the cie data.
596*eb293b8fSAndroid Build Coastguard Worker   auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
597*eb293b8fSAndroid Build Coastguard Worker   if (reg_entry == cie_loc_regs_.end()) {
598*eb293b8fSAndroid Build Coastguard Worker     if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end,
599*eb293b8fSAndroid Build Coastguard Worker                              loc_regs)) {
600*eb293b8fSAndroid Build Coastguard Worker       last_error_ = cfa.last_error();
601*eb293b8fSAndroid Build Coastguard Worker       return false;
602*eb293b8fSAndroid Build Coastguard Worker     }
603*eb293b8fSAndroid Build Coastguard Worker     DwarfLocations* cie_loc_regs = &cie_loc_regs_[fde->cie_offset];
604*eb293b8fSAndroid Build Coastguard Worker     *cie_loc_regs = *loc_regs;
605*eb293b8fSAndroid Build Coastguard Worker     cfa.set_cie_loc_regs(cie_loc_regs);
606*eb293b8fSAndroid Build Coastguard Worker   } else {
607*eb293b8fSAndroid Build Coastguard Worker     cfa.set_cie_loc_regs(&reg_entry->second);
608*eb293b8fSAndroid Build Coastguard Worker   }
609*eb293b8fSAndroid Build Coastguard Worker   if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) {
610*eb293b8fSAndroid Build Coastguard Worker     last_error_ = cfa.last_error();
611*eb293b8fSAndroid Build Coastguard Worker     return false;
612*eb293b8fSAndroid Build Coastguard Worker   }
613*eb293b8fSAndroid Build Coastguard Worker   return true;
614*eb293b8fSAndroid Build Coastguard Worker }
615*eb293b8fSAndroid Build Coastguard Worker 
616*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
Log(uint8_t indent,uint64_t pc,const DwarfFde * fde,ArchEnum arch)617*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde,
618*eb293b8fSAndroid Build Coastguard Worker                                         ArchEnum arch) {
619*eb293b8fSAndroid Build Coastguard Worker   DwarfCfa<AddressType> cfa(&memory_, fde, arch);
620*eb293b8fSAndroid Build Coastguard Worker 
621*eb293b8fSAndroid Build Coastguard Worker   // Always print the cie information.
622*eb293b8fSAndroid Build Coastguard Worker   const DwarfCie* cie = fde->cie;
623*eb293b8fSAndroid Build Coastguard Worker   if (!cfa.Log(indent, pc, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
624*eb293b8fSAndroid Build Coastguard Worker     last_error_ = cfa.last_error();
625*eb293b8fSAndroid Build Coastguard Worker     return false;
626*eb293b8fSAndroid Build Coastguard Worker   }
627*eb293b8fSAndroid Build Coastguard Worker   if (!cfa.Log(indent, pc, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
628*eb293b8fSAndroid Build Coastguard Worker     last_error_ = cfa.last_error();
629*eb293b8fSAndroid Build Coastguard Worker     return false;
630*eb293b8fSAndroid Build Coastguard Worker   }
631*eb293b8fSAndroid Build Coastguard Worker   return true;
632*eb293b8fSAndroid Build Coastguard Worker }
633*eb293b8fSAndroid Build Coastguard Worker 
634*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
Init(const SectionInfo & info)635*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::Init(const SectionInfo& info) {
636*eb293b8fSAndroid Build Coastguard Worker   if (info.flags & SHF_COMPRESSED) {
637*eb293b8fSAndroid Build Coastguard Worker     return false;
638*eb293b8fSAndroid Build Coastguard Worker   }
639*eb293b8fSAndroid Build Coastguard Worker   section_bias_ = info.bias;
640*eb293b8fSAndroid Build Coastguard Worker   entries_offset_ = info.offset;
641*eb293b8fSAndroid Build Coastguard Worker   entries_end_ = info.offset + info.size;
642*eb293b8fSAndroid Build Coastguard Worker 
643*eb293b8fSAndroid Build Coastguard Worker   memory_.clear_func_offset();
644*eb293b8fSAndroid Build Coastguard Worker   memory_.clear_text_offset();
645*eb293b8fSAndroid Build Coastguard Worker   memory_.set_cur_offset(info.offset);
646*eb293b8fSAndroid Build Coastguard Worker   pc_offset_ = info.offset;
647*eb293b8fSAndroid Build Coastguard Worker 
648*eb293b8fSAndroid Build Coastguard Worker   return true;
649*eb293b8fSAndroid Build Coastguard Worker }
650*eb293b8fSAndroid Build Coastguard Worker 
651*eb293b8fSAndroid Build Coastguard Worker // Read CIE or FDE entry at the given offset, and set the offset to the following entry.
652*eb293b8fSAndroid Build Coastguard Worker // The 'fde' argument is set only if we have seen an FDE entry.
653*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
GetNextCieOrFde(uint64_t & next_entries_offset,std::optional<DwarfFde> & fde_entry)654*eb293b8fSAndroid Build Coastguard Worker bool DwarfSectionImpl<AddressType>::GetNextCieOrFde(uint64_t& next_entries_offset,
655*eb293b8fSAndroid Build Coastguard Worker                                                     std::optional<DwarfFde>& fde_entry) {
656*eb293b8fSAndroid Build Coastguard Worker   const uint64_t start_offset = next_entries_offset;
657*eb293b8fSAndroid Build Coastguard Worker 
658*eb293b8fSAndroid Build Coastguard Worker   memory_.set_data_offset(entries_offset_);
659*eb293b8fSAndroid Build Coastguard Worker   memory_.set_cur_offset(next_entries_offset);
660*eb293b8fSAndroid Build Coastguard Worker   uint32_t value32;
661*eb293b8fSAndroid Build Coastguard Worker   if (!memory_.ReadBytes(&value32, sizeof(value32))) {
662*eb293b8fSAndroid Build Coastguard Worker     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
663*eb293b8fSAndroid Build Coastguard Worker     last_error_.address = memory_.cur_offset();
664*eb293b8fSAndroid Build Coastguard Worker     return false;
665*eb293b8fSAndroid Build Coastguard Worker   }
666*eb293b8fSAndroid Build Coastguard Worker 
667*eb293b8fSAndroid Build Coastguard Worker   uint64_t cie_offset;
668*eb293b8fSAndroid Build Coastguard Worker   uint8_t cie_fde_encoding;
669*eb293b8fSAndroid Build Coastguard Worker   bool entry_is_cie = false;
670*eb293b8fSAndroid Build Coastguard Worker   if (value32 == static_cast<uint32_t>(-1)) {
671*eb293b8fSAndroid Build Coastguard Worker     // 64 bit entry.
672*eb293b8fSAndroid Build Coastguard Worker     uint64_t value64;
673*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&value64, sizeof(value64))) {
674*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
675*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
676*eb293b8fSAndroid Build Coastguard Worker       return false;
677*eb293b8fSAndroid Build Coastguard Worker     }
678*eb293b8fSAndroid Build Coastguard Worker 
679*eb293b8fSAndroid Build Coastguard Worker     next_entries_offset = memory_.cur_offset() + value64;
680*eb293b8fSAndroid Build Coastguard Worker     // Read the Cie Id of a Cie or the pointer of the Fde.
681*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&value64, sizeof(value64))) {
682*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
683*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
684*eb293b8fSAndroid Build Coastguard Worker       return false;
685*eb293b8fSAndroid Build Coastguard Worker     }
686*eb293b8fSAndroid Build Coastguard Worker 
687*eb293b8fSAndroid Build Coastguard Worker     if (value64 == cie64_value_) {
688*eb293b8fSAndroid Build Coastguard Worker       entry_is_cie = true;
689*eb293b8fSAndroid Build Coastguard Worker       cie_fde_encoding = DW_EH_PE_udata8;
690*eb293b8fSAndroid Build Coastguard Worker     } else {
691*eb293b8fSAndroid Build Coastguard Worker       cie_offset = GetCieOffsetFromFde64(value64);
692*eb293b8fSAndroid Build Coastguard Worker     }
693*eb293b8fSAndroid Build Coastguard Worker   } else {
694*eb293b8fSAndroid Build Coastguard Worker     next_entries_offset = memory_.cur_offset() + value32;
695*eb293b8fSAndroid Build Coastguard Worker 
696*eb293b8fSAndroid Build Coastguard Worker     // 32 bit Cie
697*eb293b8fSAndroid Build Coastguard Worker     if (!memory_.ReadBytes(&value32, sizeof(value32))) {
698*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = DWARF_ERROR_MEMORY_INVALID;
699*eb293b8fSAndroid Build Coastguard Worker       last_error_.address = memory_.cur_offset();
700*eb293b8fSAndroid Build Coastguard Worker       return false;
701*eb293b8fSAndroid Build Coastguard Worker     }
702*eb293b8fSAndroid Build Coastguard Worker 
703*eb293b8fSAndroid Build Coastguard Worker     if (value32 == cie32_value_) {
704*eb293b8fSAndroid Build Coastguard Worker       entry_is_cie = true;
705*eb293b8fSAndroid Build Coastguard Worker       cie_fde_encoding = DW_EH_PE_udata4;
706*eb293b8fSAndroid Build Coastguard Worker     } else {
707*eb293b8fSAndroid Build Coastguard Worker       cie_offset = GetCieOffsetFromFde32(value32);
708*eb293b8fSAndroid Build Coastguard Worker     }
709*eb293b8fSAndroid Build Coastguard Worker   }
710*eb293b8fSAndroid Build Coastguard Worker 
711*eb293b8fSAndroid Build Coastguard Worker   if (entry_is_cie) {
712*eb293b8fSAndroid Build Coastguard Worker     if (!cie_entries_.contains(start_offset)) {
713*eb293b8fSAndroid Build Coastguard Worker       DwarfCie* cie = &cie_entries_[start_offset];
714*eb293b8fSAndroid Build Coastguard Worker       cie->lsda_encoding = DW_EH_PE_omit;
715*eb293b8fSAndroid Build Coastguard Worker       cie->cfa_instructions_end = next_entries_offset;
716*eb293b8fSAndroid Build Coastguard Worker       cie->fde_address_encoding = cie_fde_encoding;
717*eb293b8fSAndroid Build Coastguard Worker 
718*eb293b8fSAndroid Build Coastguard Worker       if (!FillInCie(cie)) {
719*eb293b8fSAndroid Build Coastguard Worker         cie_entries_.erase(start_offset);
720*eb293b8fSAndroid Build Coastguard Worker         return false;
721*eb293b8fSAndroid Build Coastguard Worker       }
722*eb293b8fSAndroid Build Coastguard Worker     }
723*eb293b8fSAndroid Build Coastguard Worker     fde_entry.reset();
724*eb293b8fSAndroid Build Coastguard Worker   } else {
725*eb293b8fSAndroid Build Coastguard Worker     fde_entry = DwarfFde{};
726*eb293b8fSAndroid Build Coastguard Worker     fde_entry->cfa_instructions_end = next_entries_offset;
727*eb293b8fSAndroid Build Coastguard Worker     fde_entry->cie_offset = cie_offset;
728*eb293b8fSAndroid Build Coastguard Worker     if (!FillInFde(&*fde_entry)) {
729*eb293b8fSAndroid Build Coastguard Worker       return false;
730*eb293b8fSAndroid Build Coastguard Worker     }
731*eb293b8fSAndroid Build Coastguard Worker   }
732*eb293b8fSAndroid Build Coastguard Worker   return true;
733*eb293b8fSAndroid Build Coastguard Worker }
734*eb293b8fSAndroid Build Coastguard Worker 
735*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
GetFdes(std::vector<const DwarfFde * > * fdes)736*eb293b8fSAndroid Build Coastguard Worker void DwarfSectionImpl<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
737*eb293b8fSAndroid Build Coastguard Worker   if (fde_index_.empty()) {
738*eb293b8fSAndroid Build Coastguard Worker     BuildFdeIndex();
739*eb293b8fSAndroid Build Coastguard Worker   }
740*eb293b8fSAndroid Build Coastguard Worker   for (auto& it : fde_index_) {
741*eb293b8fSAndroid Build Coastguard Worker     fdes->push_back(GetFdeFromOffset(it.second));
742*eb293b8fSAndroid Build Coastguard Worker   }
743*eb293b8fSAndroid Build Coastguard Worker }
744*eb293b8fSAndroid Build Coastguard Worker 
745*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
GetFdeFromPc(uint64_t pc)746*eb293b8fSAndroid Build Coastguard Worker const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromPc(uint64_t pc) {
747*eb293b8fSAndroid Build Coastguard Worker   // Ensure that the binary search table is initialized.
748*eb293b8fSAndroid Build Coastguard Worker   if (fde_index_.empty()) {
749*eb293b8fSAndroid Build Coastguard Worker     BuildFdeIndex();
750*eb293b8fSAndroid Build Coastguard Worker   }
751*eb293b8fSAndroid Build Coastguard Worker 
752*eb293b8fSAndroid Build Coastguard Worker   // Find the FDE offset in the binary search table.
753*eb293b8fSAndroid Build Coastguard Worker   auto comp = [](uint64_t pc, auto& entry) { return pc < entry.first; };
754*eb293b8fSAndroid Build Coastguard Worker   auto it = std::upper_bound(fde_index_.begin(), fde_index_.end(), pc, comp);
755*eb293b8fSAndroid Build Coastguard Worker   if (it == fde_index_.end()) {
756*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
757*eb293b8fSAndroid Build Coastguard Worker   }
758*eb293b8fSAndroid Build Coastguard Worker 
759*eb293b8fSAndroid Build Coastguard Worker   // Load the full FDE entry based on the offset.
760*eb293b8fSAndroid Build Coastguard Worker   const DwarfFde* fde = GetFdeFromOffset(/*fde_offset=*/it->second);
761*eb293b8fSAndroid Build Coastguard Worker   return fde != nullptr && fde->pc_start <= pc ? fde : nullptr;
762*eb293b8fSAndroid Build Coastguard Worker }
763*eb293b8fSAndroid Build Coastguard Worker 
764*eb293b8fSAndroid Build Coastguard Worker // Create binary search table to make FDE lookups fast (sorted by pc_end).
765*eb293b8fSAndroid Build Coastguard Worker // We store only the FDE offset rather than the full entry to save memory.
766*eb293b8fSAndroid Build Coastguard Worker //
767*eb293b8fSAndroid Build Coastguard Worker // If there are overlapping entries, it inserts additional entries to ensure
768*eb293b8fSAndroid Build Coastguard Worker // that one of the overlapping entries is found (it is undefined which one).
769*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
BuildFdeIndex()770*eb293b8fSAndroid Build Coastguard Worker void DwarfSectionImpl<AddressType>::BuildFdeIndex() {
771*eb293b8fSAndroid Build Coastguard Worker   struct FdeInfo {
772*eb293b8fSAndroid Build Coastguard Worker     uint64_t pc_start, pc_end, fde_offset;
773*eb293b8fSAndroid Build Coastguard Worker   };
774*eb293b8fSAndroid Build Coastguard Worker   std::vector<FdeInfo> fdes;
775*eb293b8fSAndroid Build Coastguard Worker   for (uint64_t offset = entries_offset_; offset < entries_end_;) {
776*eb293b8fSAndroid Build Coastguard Worker     const uint64_t initial_offset = offset;
777*eb293b8fSAndroid Build Coastguard Worker     std::optional<DwarfFde> fde;
778*eb293b8fSAndroid Build Coastguard Worker     if (!GetNextCieOrFde(offset, fde)) {
779*eb293b8fSAndroid Build Coastguard Worker       break;
780*eb293b8fSAndroid Build Coastguard Worker     }
781*eb293b8fSAndroid Build Coastguard Worker     if (fde.has_value() && /* defensive check */ (fde->pc_start < fde->pc_end)) {
782*eb293b8fSAndroid Build Coastguard Worker       fdes.push_back({fde->pc_start, fde->pc_end, initial_offset});
783*eb293b8fSAndroid Build Coastguard Worker     }
784*eb293b8fSAndroid Build Coastguard Worker     if (offset <= initial_offset) {
785*eb293b8fSAndroid Build Coastguard Worker       break;  // Jump back. Simply consider the processing done in this case.
786*eb293b8fSAndroid Build Coastguard Worker     }
787*eb293b8fSAndroid Build Coastguard Worker   }
788*eb293b8fSAndroid Build Coastguard Worker   std::sort(fdes.begin(), fdes.end(), [](const FdeInfo& a, const FdeInfo& b) {
789*eb293b8fSAndroid Build Coastguard Worker     return std::tie(a.pc_end, a.fde_offset) < std::tie(b.pc_end, b.fde_offset);
790*eb293b8fSAndroid Build Coastguard Worker   });
791*eb293b8fSAndroid Build Coastguard Worker 
792*eb293b8fSAndroid Build Coastguard Worker   // If there are overlapping entries, ensure that we can always find one of them.
793*eb293b8fSAndroid Build Coastguard Worker   // For example, for entries:   [300, 350)  [400, 450)  [100, 550)  [600, 650)
794*eb293b8fSAndroid Build Coastguard Worker   // We add the following:  [100, 300)  [100, 400)
795*eb293b8fSAndroid Build Coastguard Worker   // Which ensures that the [100, 550) entry can be found in its whole range.
796*eb293b8fSAndroid Build Coastguard Worker   if (!fdes.empty()) {
797*eb293b8fSAndroid Build Coastguard Worker     FdeInfo filling = fdes.back();  // Entry with the minimal pc_start seen so far.
798*eb293b8fSAndroid Build Coastguard Worker     for (ssize_t i = fdes.size() - 1; i >= 0; i--) {  // Iterate backwards.
799*eb293b8fSAndroid Build Coastguard Worker       uint64_t prev_pc_end = (i > 0) ? fdes[i - 1].pc_end : 0;
800*eb293b8fSAndroid Build Coastguard Worker       // If there is a gap between entries and the filling reaches the gap, fill it.
801*eb293b8fSAndroid Build Coastguard Worker       if (prev_pc_end < fdes[i].pc_start && filling.pc_start < fdes[i].pc_start) {
802*eb293b8fSAndroid Build Coastguard Worker         fdes.push_back({filling.pc_start, fdes[i].pc_start, filling.fde_offset});
803*eb293b8fSAndroid Build Coastguard Worker       }
804*eb293b8fSAndroid Build Coastguard Worker       if (fdes[i].pc_start < filling.pc_start) {
805*eb293b8fSAndroid Build Coastguard Worker         filling = fdes[i];
806*eb293b8fSAndroid Build Coastguard Worker       }
807*eb293b8fSAndroid Build Coastguard Worker     }
808*eb293b8fSAndroid Build Coastguard Worker   }
809*eb293b8fSAndroid Build Coastguard Worker 
810*eb293b8fSAndroid Build Coastguard Worker   // Copy data to the final binary search table (pc_end, fde_offset) and sort it.
811*eb293b8fSAndroid Build Coastguard Worker   fde_index_.reserve(fdes.size());
812*eb293b8fSAndroid Build Coastguard Worker   for (const FdeInfo& it : fdes) {
813*eb293b8fSAndroid Build Coastguard Worker     fde_index_.emplace_back(it.pc_end, it.fde_offset);
814*eb293b8fSAndroid Build Coastguard Worker   }
815*eb293b8fSAndroid Build Coastguard Worker   if (!std::is_sorted(fde_index_.begin(), fde_index_.end())) {
816*eb293b8fSAndroid Build Coastguard Worker     std::sort(fde_index_.begin(), fde_index_.end());
817*eb293b8fSAndroid Build Coastguard Worker   }
818*eb293b8fSAndroid Build Coastguard Worker }
819*eb293b8fSAndroid Build Coastguard Worker 
820*eb293b8fSAndroid Build Coastguard Worker // Explicitly instantiate DwarfSectionImpl
821*eb293b8fSAndroid Build Coastguard Worker template class DwarfSectionImpl<uint32_t>;
822*eb293b8fSAndroid Build Coastguard Worker template class DwarfSectionImpl<uint64_t>;
823*eb293b8fSAndroid Build Coastguard Worker 
824*eb293b8fSAndroid Build Coastguard Worker // Explicitly instantiate DwarfDebugFrame
825*eb293b8fSAndroid Build Coastguard Worker template class DwarfDebugFrame<uint32_t>;
826*eb293b8fSAndroid Build Coastguard Worker template class DwarfDebugFrame<uint64_t>;
827*eb293b8fSAndroid Build Coastguard Worker 
828*eb293b8fSAndroid Build Coastguard Worker // Explicitly instantiate DwarfEhFrame
829*eb293b8fSAndroid Build Coastguard Worker template class DwarfEhFrame<uint32_t>;
830*eb293b8fSAndroid Build Coastguard Worker template class DwarfEhFrame<uint64_t>;
831*eb293b8fSAndroid Build Coastguard Worker 
832*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
833