xref: /aosp_15_r20/system/unwinding/libunwindstack/Unwinder.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 #define _GNU_SOURCE 1
18*eb293b8fSAndroid Build Coastguard Worker #include <elf.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <inttypes.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
21*eb293b8fSAndroid Build Coastguard Worker #include <string.h>
22*eb293b8fSAndroid Build Coastguard Worker #include <sys/mman.h>
23*eb293b8fSAndroid Build Coastguard Worker #include <sys/types.h>
24*eb293b8fSAndroid Build Coastguard Worker #include <unistd.h>
25*eb293b8fSAndroid Build Coastguard Worker 
26*eb293b8fSAndroid Build Coastguard Worker #include <algorithm>
27*eb293b8fSAndroid Build Coastguard Worker #include <memory>
28*eb293b8fSAndroid Build Coastguard Worker #include <string>
29*eb293b8fSAndroid Build Coastguard Worker 
30*eb293b8fSAndroid Build Coastguard Worker #include <android-base/file.h>
31*eb293b8fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
32*eb293b8fSAndroid Build Coastguard Worker 
33*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Demangle.h>
34*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DexFiles.h>
35*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
36*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/JitDebug.h>
37*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MapInfo.h>
38*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
39*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
40*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h>
41*eb293b8fSAndroid Build Coastguard Worker 
42*eb293b8fSAndroid Build Coastguard Worker #include "Check.h"
43*eb293b8fSAndroid Build Coastguard Worker 
44*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
45*eb293b8fSAndroid Build Coastguard Worker 
46*eb293b8fSAndroid Build Coastguard Worker // Inject extra 'virtual' frame that represents the dex pc data.
47*eb293b8fSAndroid Build Coastguard Worker // The dex pc is a magic register defined in the Mterp interpreter,
48*eb293b8fSAndroid Build Coastguard Worker // and thus it will be restored/observed in the frame after it.
49*eb293b8fSAndroid Build Coastguard Worker // Adding the dex frame first here will create something like:
50*eb293b8fSAndroid Build Coastguard Worker //   #7 pc 0015fa20 core.vdex   java.util.Arrays.binarySearch+8
51*eb293b8fSAndroid Build Coastguard Worker //   #8 pc 006b1ba1 libartd.so  ExecuteMterpImpl+14625
52*eb293b8fSAndroid Build Coastguard Worker //   #9 pc 0039a1ef libartd.so  art::interpreter::Execute+719
FillInDexFrame()53*eb293b8fSAndroid Build Coastguard Worker void Unwinder::FillInDexFrame() {
54*eb293b8fSAndroid Build Coastguard Worker   size_t frame_num = frames_.size();
55*eb293b8fSAndroid Build Coastguard Worker   frames_.resize(frame_num + 1);
56*eb293b8fSAndroid Build Coastguard Worker   FrameData* frame = &frames_.at(frame_num);
57*eb293b8fSAndroid Build Coastguard Worker   frame->num = frame_num;
58*eb293b8fSAndroid Build Coastguard Worker 
59*eb293b8fSAndroid Build Coastguard Worker   uint64_t dex_pc = regs_->dex_pc();
60*eb293b8fSAndroid Build Coastguard Worker   frame->pc = dex_pc;
61*eb293b8fSAndroid Build Coastguard Worker   frame->sp = regs_->sp();
62*eb293b8fSAndroid Build Coastguard Worker 
63*eb293b8fSAndroid Build Coastguard Worker   frame->map_info = maps_->Find(dex_pc);
64*eb293b8fSAndroid Build Coastguard Worker   if (frame->map_info != nullptr) {
65*eb293b8fSAndroid Build Coastguard Worker     frame->rel_pc = dex_pc - frame->map_info->start();
66*eb293b8fSAndroid Build Coastguard Worker     // Initialize the load bias for this map so subsequent calls
67*eb293b8fSAndroid Build Coastguard Worker     // to GetLoadBias() will always return data.
68*eb293b8fSAndroid Build Coastguard Worker     frame->map_info->set_load_bias(0);
69*eb293b8fSAndroid Build Coastguard Worker   } else {
70*eb293b8fSAndroid Build Coastguard Worker     frame->rel_pc = dex_pc;
71*eb293b8fSAndroid Build Coastguard Worker     warnings_ |= WARNING_DEX_PC_NOT_IN_MAP;
72*eb293b8fSAndroid Build Coastguard Worker     return;
73*eb293b8fSAndroid Build Coastguard Worker   }
74*eb293b8fSAndroid Build Coastguard Worker 
75*eb293b8fSAndroid Build Coastguard Worker   if (!resolve_names_) {
76*eb293b8fSAndroid Build Coastguard Worker     return;
77*eb293b8fSAndroid Build Coastguard Worker   }
78*eb293b8fSAndroid Build Coastguard Worker 
79*eb293b8fSAndroid Build Coastguard Worker #if defined(DEXFILE_SUPPORT)
80*eb293b8fSAndroid Build Coastguard Worker   if (dex_files_ == nullptr) {
81*eb293b8fSAndroid Build Coastguard Worker     return;
82*eb293b8fSAndroid Build Coastguard Worker   }
83*eb293b8fSAndroid Build Coastguard Worker 
84*eb293b8fSAndroid Build Coastguard Worker   dex_files_->GetFunctionName(maps_, dex_pc, &frame->function_name, &frame->function_offset);
85*eb293b8fSAndroid Build Coastguard Worker #endif
86*eb293b8fSAndroid Build Coastguard Worker }
87*eb293b8fSAndroid Build Coastguard Worker 
FillInFrame(std::shared_ptr<MapInfo> & map_info,Elf *,uint64_t rel_pc,uint64_t pc_adjustment)88*eb293b8fSAndroid Build Coastguard Worker FrameData* Unwinder::FillInFrame(std::shared_ptr<MapInfo>& map_info, Elf* /*elf*/, uint64_t rel_pc,
89*eb293b8fSAndroid Build Coastguard Worker                                  uint64_t pc_adjustment) {
90*eb293b8fSAndroid Build Coastguard Worker   size_t frame_num = frames_.size();
91*eb293b8fSAndroid Build Coastguard Worker   frames_.resize(frame_num + 1);
92*eb293b8fSAndroid Build Coastguard Worker   FrameData* frame = &frames_.at(frame_num);
93*eb293b8fSAndroid Build Coastguard Worker   frame->num = frame_num;
94*eb293b8fSAndroid Build Coastguard Worker   frame->sp = regs_->sp();
95*eb293b8fSAndroid Build Coastguard Worker   frame->rel_pc = rel_pc - pc_adjustment;
96*eb293b8fSAndroid Build Coastguard Worker   frame->pc = regs_->pc() - pc_adjustment;
97*eb293b8fSAndroid Build Coastguard Worker 
98*eb293b8fSAndroid Build Coastguard Worker   if (map_info == nullptr) {
99*eb293b8fSAndroid Build Coastguard Worker     // Nothing else to update.
100*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
101*eb293b8fSAndroid Build Coastguard Worker   }
102*eb293b8fSAndroid Build Coastguard Worker 
103*eb293b8fSAndroid Build Coastguard Worker   frame->map_info = map_info;
104*eb293b8fSAndroid Build Coastguard Worker 
105*eb293b8fSAndroid Build Coastguard Worker   return frame;
106*eb293b8fSAndroid Build Coastguard Worker }
107*eb293b8fSAndroid Build Coastguard Worker 
ShouldStop(const std::vector<std::string> * map_suffixes_to_ignore,const std::string & map_name)108*eb293b8fSAndroid Build Coastguard Worker static bool ShouldStop(const std::vector<std::string>* map_suffixes_to_ignore,
109*eb293b8fSAndroid Build Coastguard Worker                        const std::string& map_name) {
110*eb293b8fSAndroid Build Coastguard Worker   if (map_suffixes_to_ignore == nullptr) {
111*eb293b8fSAndroid Build Coastguard Worker     return false;
112*eb293b8fSAndroid Build Coastguard Worker   }
113*eb293b8fSAndroid Build Coastguard Worker   auto pos = map_name.find_last_of('.');
114*eb293b8fSAndroid Build Coastguard Worker   if (pos == std::string::npos) {
115*eb293b8fSAndroid Build Coastguard Worker     return false;
116*eb293b8fSAndroid Build Coastguard Worker   }
117*eb293b8fSAndroid Build Coastguard Worker 
118*eb293b8fSAndroid Build Coastguard Worker   return std::find(map_suffixes_to_ignore->begin(), map_suffixes_to_ignore->end(),
119*eb293b8fSAndroid Build Coastguard Worker                    map_name.substr(pos + 1)) != map_suffixes_to_ignore->end();
120*eb293b8fSAndroid Build Coastguard Worker }
121*eb293b8fSAndroid Build Coastguard Worker 
Unwind(const std::vector<std::string> * initial_map_names_to_skip,const std::vector<std::string> * map_suffixes_to_ignore)122*eb293b8fSAndroid Build Coastguard Worker void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
123*eb293b8fSAndroid Build Coastguard Worker                       const std::vector<std::string>* map_suffixes_to_ignore) {
124*eb293b8fSAndroid Build Coastguard Worker   CHECK(arch_ != ARCH_UNKNOWN);
125*eb293b8fSAndroid Build Coastguard Worker   ClearErrors();
126*eb293b8fSAndroid Build Coastguard Worker 
127*eb293b8fSAndroid Build Coastguard Worker   frames_.clear();
128*eb293b8fSAndroid Build Coastguard Worker 
129*eb293b8fSAndroid Build Coastguard Worker   // Clear any cached data from previous unwinds.
130*eb293b8fSAndroid Build Coastguard Worker   process_memory_->Clear();
131*eb293b8fSAndroid Build Coastguard Worker 
132*eb293b8fSAndroid Build Coastguard Worker   if (maps_->Find(regs_->pc()) == nullptr) {
133*eb293b8fSAndroid Build Coastguard Worker     regs_->fallback_pc();
134*eb293b8fSAndroid Build Coastguard Worker   }
135*eb293b8fSAndroid Build Coastguard Worker 
136*eb293b8fSAndroid Build Coastguard Worker   bool return_address_attempt = false;
137*eb293b8fSAndroid Build Coastguard Worker   bool adjust_pc = false;
138*eb293b8fSAndroid Build Coastguard Worker   for (; frames_.size() < max_frames_;) {
139*eb293b8fSAndroid Build Coastguard Worker     uint64_t cur_pc = regs_->pc();
140*eb293b8fSAndroid Build Coastguard Worker     uint64_t cur_sp = regs_->sp();
141*eb293b8fSAndroid Build Coastguard Worker 
142*eb293b8fSAndroid Build Coastguard Worker     std::shared_ptr<MapInfo> map_info = maps_->Find(regs_->pc());
143*eb293b8fSAndroid Build Coastguard Worker     uint64_t pc_adjustment = 0;
144*eb293b8fSAndroid Build Coastguard Worker     uint64_t step_pc;
145*eb293b8fSAndroid Build Coastguard Worker     uint64_t rel_pc;
146*eb293b8fSAndroid Build Coastguard Worker     Elf* elf;
147*eb293b8fSAndroid Build Coastguard Worker     bool ignore_frame = false;
148*eb293b8fSAndroid Build Coastguard Worker     if (map_info == nullptr) {
149*eb293b8fSAndroid Build Coastguard Worker       step_pc = regs_->pc();
150*eb293b8fSAndroid Build Coastguard Worker       rel_pc = step_pc;
151*eb293b8fSAndroid Build Coastguard Worker       // If we get invalid map via return_address_attempt, don't hide error for the previous frame.
152*eb293b8fSAndroid Build Coastguard Worker       if (!return_address_attempt || last_error_.code == ERROR_NONE) {
153*eb293b8fSAndroid Build Coastguard Worker         last_error_.code = ERROR_INVALID_MAP;
154*eb293b8fSAndroid Build Coastguard Worker         last_error_.address = step_pc;
155*eb293b8fSAndroid Build Coastguard Worker       }
156*eb293b8fSAndroid Build Coastguard Worker       elf = nullptr;
157*eb293b8fSAndroid Build Coastguard Worker     } else {
158*eb293b8fSAndroid Build Coastguard Worker       ignore_frame =
159*eb293b8fSAndroid Build Coastguard Worker           initial_map_names_to_skip != nullptr &&
160*eb293b8fSAndroid Build Coastguard Worker           std::find(initial_map_names_to_skip->begin(), initial_map_names_to_skip->end(),
161*eb293b8fSAndroid Build Coastguard Worker                     android::base::Basename(map_info->name())) != initial_map_names_to_skip->end();
162*eb293b8fSAndroid Build Coastguard Worker       if (!ignore_frame && ShouldStop(map_suffixes_to_ignore, map_info->name())) {
163*eb293b8fSAndroid Build Coastguard Worker         break;
164*eb293b8fSAndroid Build Coastguard Worker       }
165*eb293b8fSAndroid Build Coastguard Worker       elf = map_info->GetElf(process_memory_, arch_);
166*eb293b8fSAndroid Build Coastguard Worker       step_pc = regs_->pc();
167*eb293b8fSAndroid Build Coastguard Worker       rel_pc = elf->GetRelPc(step_pc, map_info.get());
168*eb293b8fSAndroid Build Coastguard Worker       // Everyone except elf data in gdb jit debug maps uses the relative pc.
169*eb293b8fSAndroid Build Coastguard Worker       if (!(map_info->flags() & MAPS_FLAGS_JIT_SYMFILE_MAP)) {
170*eb293b8fSAndroid Build Coastguard Worker         step_pc = rel_pc;
171*eb293b8fSAndroid Build Coastguard Worker       }
172*eb293b8fSAndroid Build Coastguard Worker       if (adjust_pc) {
173*eb293b8fSAndroid Build Coastguard Worker         pc_adjustment = GetPcAdjustment(rel_pc, elf, arch_);
174*eb293b8fSAndroid Build Coastguard Worker       } else {
175*eb293b8fSAndroid Build Coastguard Worker         pc_adjustment = 0;
176*eb293b8fSAndroid Build Coastguard Worker       }
177*eb293b8fSAndroid Build Coastguard Worker       step_pc -= pc_adjustment;
178*eb293b8fSAndroid Build Coastguard Worker 
179*eb293b8fSAndroid Build Coastguard Worker       // If the pc is in an invalid elf file, try and get an Elf object
180*eb293b8fSAndroid Build Coastguard Worker       // using the jit debug information.
181*eb293b8fSAndroid Build Coastguard Worker       if (!elf->valid() && jit_debug_ != nullptr && (map_info->flags() & PROT_EXEC)) {
182*eb293b8fSAndroid Build Coastguard Worker         uint64_t adjusted_jit_pc = regs_->pc() - pc_adjustment;
183*eb293b8fSAndroid Build Coastguard Worker         Elf* jit_elf = jit_debug_->Find(maps_, adjusted_jit_pc);
184*eb293b8fSAndroid Build Coastguard Worker         if (jit_elf != nullptr) {
185*eb293b8fSAndroid Build Coastguard Worker           // The jit debug information requires a non relative adjusted pc.
186*eb293b8fSAndroid Build Coastguard Worker           step_pc = adjusted_jit_pc;
187*eb293b8fSAndroid Build Coastguard Worker           elf = jit_elf;
188*eb293b8fSAndroid Build Coastguard Worker         }
189*eb293b8fSAndroid Build Coastguard Worker       }
190*eb293b8fSAndroid Build Coastguard Worker     }
191*eb293b8fSAndroid Build Coastguard Worker 
192*eb293b8fSAndroid Build Coastguard Worker     FrameData* frame = nullptr;
193*eb293b8fSAndroid Build Coastguard Worker     if (!ignore_frame) {
194*eb293b8fSAndroid Build Coastguard Worker       if (regs_->dex_pc() != 0) {
195*eb293b8fSAndroid Build Coastguard Worker         // Add a frame to represent the dex file.
196*eb293b8fSAndroid Build Coastguard Worker         FillInDexFrame();
197*eb293b8fSAndroid Build Coastguard Worker         // Clear the dex pc so that we don't repeat this frame later.
198*eb293b8fSAndroid Build Coastguard Worker         regs_->set_dex_pc(0);
199*eb293b8fSAndroid Build Coastguard Worker 
200*eb293b8fSAndroid Build Coastguard Worker         // Make sure there is enough room for the real frame.
201*eb293b8fSAndroid Build Coastguard Worker         if (frames_.size() == max_frames_) {
202*eb293b8fSAndroid Build Coastguard Worker           last_error_.code = ERROR_MAX_FRAMES_EXCEEDED;
203*eb293b8fSAndroid Build Coastguard Worker           break;
204*eb293b8fSAndroid Build Coastguard Worker         }
205*eb293b8fSAndroid Build Coastguard Worker       }
206*eb293b8fSAndroid Build Coastguard Worker 
207*eb293b8fSAndroid Build Coastguard Worker       frame = FillInFrame(map_info, elf, rel_pc, pc_adjustment);
208*eb293b8fSAndroid Build Coastguard Worker 
209*eb293b8fSAndroid Build Coastguard Worker       // Once a frame is added, stop skipping frames.
210*eb293b8fSAndroid Build Coastguard Worker       initial_map_names_to_skip = nullptr;
211*eb293b8fSAndroid Build Coastguard Worker     }
212*eb293b8fSAndroid Build Coastguard Worker     adjust_pc = true;
213*eb293b8fSAndroid Build Coastguard Worker 
214*eb293b8fSAndroid Build Coastguard Worker     bool stepped = false;
215*eb293b8fSAndroid Build Coastguard Worker     bool in_device_map = false;
216*eb293b8fSAndroid Build Coastguard Worker     bool finished = false;
217*eb293b8fSAndroid Build Coastguard Worker     if (map_info != nullptr) {
218*eb293b8fSAndroid Build Coastguard Worker       if (map_info->flags() & MAPS_FLAGS_DEVICE_MAP) {
219*eb293b8fSAndroid Build Coastguard Worker         // Do not stop here, fall through in case we are
220*eb293b8fSAndroid Build Coastguard Worker         // in the speculative unwind path and need to remove
221*eb293b8fSAndroid Build Coastguard Worker         // some of the speculative frames.
222*eb293b8fSAndroid Build Coastguard Worker         in_device_map = true;
223*eb293b8fSAndroid Build Coastguard Worker       } else {
224*eb293b8fSAndroid Build Coastguard Worker         auto sp_info = maps_->Find(regs_->sp());
225*eb293b8fSAndroid Build Coastguard Worker         if (sp_info != nullptr && sp_info->flags() & MAPS_FLAGS_DEVICE_MAP) {
226*eb293b8fSAndroid Build Coastguard Worker           // Do not stop here, fall through in case we are
227*eb293b8fSAndroid Build Coastguard Worker           // in the speculative unwind path and need to remove
228*eb293b8fSAndroid Build Coastguard Worker           // some of the speculative frames.
229*eb293b8fSAndroid Build Coastguard Worker           in_device_map = true;
230*eb293b8fSAndroid Build Coastguard Worker         } else {
231*eb293b8fSAndroid Build Coastguard Worker           bool is_signal_frame = false;
232*eb293b8fSAndroid Build Coastguard Worker           if (elf->StepIfSignalHandler(rel_pc, regs_, process_memory_.get())) {
233*eb293b8fSAndroid Build Coastguard Worker             stepped = true;
234*eb293b8fSAndroid Build Coastguard Worker             is_signal_frame = true;
235*eb293b8fSAndroid Build Coastguard Worker           } else if (elf->Step(step_pc, regs_, process_memory_.get(), &finished,
236*eb293b8fSAndroid Build Coastguard Worker                                &is_signal_frame)) {
237*eb293b8fSAndroid Build Coastguard Worker             stepped = true;
238*eb293b8fSAndroid Build Coastguard Worker           }
239*eb293b8fSAndroid Build Coastguard Worker           if (is_signal_frame && frame != nullptr) {
240*eb293b8fSAndroid Build Coastguard Worker             // Need to adjust the relative pc because the signal handler
241*eb293b8fSAndroid Build Coastguard Worker             // pc should not be adjusted.
242*eb293b8fSAndroid Build Coastguard Worker             frame->rel_pc = rel_pc;
243*eb293b8fSAndroid Build Coastguard Worker             frame->pc += pc_adjustment;
244*eb293b8fSAndroid Build Coastguard Worker             step_pc = rel_pc;
245*eb293b8fSAndroid Build Coastguard Worker           }
246*eb293b8fSAndroid Build Coastguard Worker           elf->GetLastError(&last_error_);
247*eb293b8fSAndroid Build Coastguard Worker         }
248*eb293b8fSAndroid Build Coastguard Worker       }
249*eb293b8fSAndroid Build Coastguard Worker     }
250*eb293b8fSAndroid Build Coastguard Worker 
251*eb293b8fSAndroid Build Coastguard Worker     if (frame != nullptr) {
252*eb293b8fSAndroid Build Coastguard Worker       if (!resolve_names_ ||
253*eb293b8fSAndroid Build Coastguard Worker           !elf->GetFunctionName(step_pc, &frame->function_name, &frame->function_offset)) {
254*eb293b8fSAndroid Build Coastguard Worker         frame->function_name = "";
255*eb293b8fSAndroid Build Coastguard Worker         frame->function_offset = 0;
256*eb293b8fSAndroid Build Coastguard Worker       }
257*eb293b8fSAndroid Build Coastguard Worker     }
258*eb293b8fSAndroid Build Coastguard Worker 
259*eb293b8fSAndroid Build Coastguard Worker     if (finished) {
260*eb293b8fSAndroid Build Coastguard Worker       break;
261*eb293b8fSAndroid Build Coastguard Worker     }
262*eb293b8fSAndroid Build Coastguard Worker 
263*eb293b8fSAndroid Build Coastguard Worker     if (!stepped) {
264*eb293b8fSAndroid Build Coastguard Worker       if (return_address_attempt) {
265*eb293b8fSAndroid Build Coastguard Worker         // Only remove the speculative frame if there are more than two frames
266*eb293b8fSAndroid Build Coastguard Worker         // or the pc in the first frame is in a valid map.
267*eb293b8fSAndroid Build Coastguard Worker         // This allows for a case where the code jumps into the middle of
268*eb293b8fSAndroid Build Coastguard Worker         // nowhere, but there is no other unwind information after that.
269*eb293b8fSAndroid Build Coastguard Worker         if (frames_.size() > 2 || (frames_.size() > 0 && maps_->Find(frames_[0].pc) != nullptr)) {
270*eb293b8fSAndroid Build Coastguard Worker           // Remove the speculative frame.
271*eb293b8fSAndroid Build Coastguard Worker           frames_.pop_back();
272*eb293b8fSAndroid Build Coastguard Worker         }
273*eb293b8fSAndroid Build Coastguard Worker         break;
274*eb293b8fSAndroid Build Coastguard Worker       } else if (in_device_map) {
275*eb293b8fSAndroid Build Coastguard Worker         // Do not attempt any other unwinding, pc or sp is in a device
276*eb293b8fSAndroid Build Coastguard Worker         // map.
277*eb293b8fSAndroid Build Coastguard Worker         break;
278*eb293b8fSAndroid Build Coastguard Worker       } else {
279*eb293b8fSAndroid Build Coastguard Worker         // Steping didn't work, try this secondary method.
280*eb293b8fSAndroid Build Coastguard Worker         if (!regs_->SetPcFromReturnAddress(process_memory_.get())) {
281*eb293b8fSAndroid Build Coastguard Worker           break;
282*eb293b8fSAndroid Build Coastguard Worker         }
283*eb293b8fSAndroid Build Coastguard Worker         return_address_attempt = true;
284*eb293b8fSAndroid Build Coastguard Worker       }
285*eb293b8fSAndroid Build Coastguard Worker     } else {
286*eb293b8fSAndroid Build Coastguard Worker       return_address_attempt = false;
287*eb293b8fSAndroid Build Coastguard Worker       if (max_frames_ == frames_.size()) {
288*eb293b8fSAndroid Build Coastguard Worker         last_error_.code = ERROR_MAX_FRAMES_EXCEEDED;
289*eb293b8fSAndroid Build Coastguard Worker       }
290*eb293b8fSAndroid Build Coastguard Worker     }
291*eb293b8fSAndroid Build Coastguard Worker 
292*eb293b8fSAndroid Build Coastguard Worker     // If the pc and sp didn't change, then consider everything stopped.
293*eb293b8fSAndroid Build Coastguard Worker     if (cur_pc == regs_->pc() && cur_sp == regs_->sp()) {
294*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = ERROR_REPEATED_FRAME;
295*eb293b8fSAndroid Build Coastguard Worker       break;
296*eb293b8fSAndroid Build Coastguard Worker     }
297*eb293b8fSAndroid Build Coastguard Worker   }
298*eb293b8fSAndroid Build Coastguard Worker }
299*eb293b8fSAndroid Build Coastguard Worker 
FormatFrame(const FrameData & frame) const300*eb293b8fSAndroid Build Coastguard Worker std::string Unwinder::FormatFrame(const FrameData& frame) const {
301*eb293b8fSAndroid Build Coastguard Worker   return FormatFrame(arch_, frame, display_build_id_);
302*eb293b8fSAndroid Build Coastguard Worker }
303*eb293b8fSAndroid Build Coastguard Worker 
FormatFrame(ArchEnum arch,const FrameData & frame,bool display_build_id)304*eb293b8fSAndroid Build Coastguard Worker std::string Unwinder::FormatFrame(ArchEnum arch, const FrameData& frame, bool display_build_id) {
305*eb293b8fSAndroid Build Coastguard Worker   std::string data;
306*eb293b8fSAndroid Build Coastguard Worker   if (ArchIs32Bit(arch)) {
307*eb293b8fSAndroid Build Coastguard Worker     data += android::base::StringPrintf("  #%02zu pc %08" PRIx64, frame.num, frame.rel_pc);
308*eb293b8fSAndroid Build Coastguard Worker   } else {
309*eb293b8fSAndroid Build Coastguard Worker     data += android::base::StringPrintf("  #%02zu pc %016" PRIx64, frame.num, frame.rel_pc);
310*eb293b8fSAndroid Build Coastguard Worker   }
311*eb293b8fSAndroid Build Coastguard Worker 
312*eb293b8fSAndroid Build Coastguard Worker   auto map_info = frame.map_info;
313*eb293b8fSAndroid Build Coastguard Worker   if (map_info == nullptr) {
314*eb293b8fSAndroid Build Coastguard Worker     // No valid map associated with this frame.
315*eb293b8fSAndroid Build Coastguard Worker     data += "  <unknown>";
316*eb293b8fSAndroid Build Coastguard Worker   } else if (!map_info->name().empty()) {
317*eb293b8fSAndroid Build Coastguard Worker     data += "  ";
318*eb293b8fSAndroid Build Coastguard Worker     data += map_info->GetFullName();
319*eb293b8fSAndroid Build Coastguard Worker   } else {
320*eb293b8fSAndroid Build Coastguard Worker     data += android::base::StringPrintf("  <anonymous:%" PRIx64 ">", map_info->start());
321*eb293b8fSAndroid Build Coastguard Worker   }
322*eb293b8fSAndroid Build Coastguard Worker 
323*eb293b8fSAndroid Build Coastguard Worker   if (map_info != nullptr && map_info->elf_start_offset() != 0) {
324*eb293b8fSAndroid Build Coastguard Worker     data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", map_info->elf_start_offset());
325*eb293b8fSAndroid Build Coastguard Worker   }
326*eb293b8fSAndroid Build Coastguard Worker 
327*eb293b8fSAndroid Build Coastguard Worker   if (!frame.function_name.empty()) {
328*eb293b8fSAndroid Build Coastguard Worker     data += " (" + DemangleNameIfNeeded(frame.function_name);
329*eb293b8fSAndroid Build Coastguard Worker     if (frame.function_offset != 0) {
330*eb293b8fSAndroid Build Coastguard Worker       data += android::base::StringPrintf("+%" PRId64, frame.function_offset);
331*eb293b8fSAndroid Build Coastguard Worker     }
332*eb293b8fSAndroid Build Coastguard Worker     data += ')';
333*eb293b8fSAndroid Build Coastguard Worker   }
334*eb293b8fSAndroid Build Coastguard Worker 
335*eb293b8fSAndroid Build Coastguard Worker   if (map_info != nullptr && display_build_id) {
336*eb293b8fSAndroid Build Coastguard Worker     std::string build_id = map_info->GetPrintableBuildID();
337*eb293b8fSAndroid Build Coastguard Worker     if (!build_id.empty()) {
338*eb293b8fSAndroid Build Coastguard Worker       data += " (BuildId: " + build_id + ')';
339*eb293b8fSAndroid Build Coastguard Worker     }
340*eb293b8fSAndroid Build Coastguard Worker   }
341*eb293b8fSAndroid Build Coastguard Worker   return data;
342*eb293b8fSAndroid Build Coastguard Worker }
343*eb293b8fSAndroid Build Coastguard Worker 
FormatFrame(size_t frame_num) const344*eb293b8fSAndroid Build Coastguard Worker std::string Unwinder::FormatFrame(size_t frame_num) const {
345*eb293b8fSAndroid Build Coastguard Worker   if (frame_num >= frames_.size()) {
346*eb293b8fSAndroid Build Coastguard Worker     return "";
347*eb293b8fSAndroid Build Coastguard Worker   }
348*eb293b8fSAndroid Build Coastguard Worker   return FormatFrame(arch_, frames_[frame_num], display_build_id_);
349*eb293b8fSAndroid Build Coastguard Worker }
350*eb293b8fSAndroid Build Coastguard Worker 
SetJitDebug(JitDebug * jit_debug)351*eb293b8fSAndroid Build Coastguard Worker void Unwinder::SetJitDebug(JitDebug* jit_debug) {
352*eb293b8fSAndroid Build Coastguard Worker   jit_debug_ = jit_debug;
353*eb293b8fSAndroid Build Coastguard Worker }
354*eb293b8fSAndroid Build Coastguard Worker 
SetDexFiles(DexFiles * dex_files)355*eb293b8fSAndroid Build Coastguard Worker void Unwinder::SetDexFiles(DexFiles* dex_files) {
356*eb293b8fSAndroid Build Coastguard Worker   dex_files_ = dex_files;
357*eb293b8fSAndroid Build Coastguard Worker }
358*eb293b8fSAndroid Build Coastguard Worker 
Init()359*eb293b8fSAndroid Build Coastguard Worker bool UnwinderFromPid::Init() {
360*eb293b8fSAndroid Build Coastguard Worker   CHECK(arch_ != ARCH_UNKNOWN);
361*eb293b8fSAndroid Build Coastguard Worker   if (initted_) {
362*eb293b8fSAndroid Build Coastguard Worker     return true;
363*eb293b8fSAndroid Build Coastguard Worker   }
364*eb293b8fSAndroid Build Coastguard Worker   initted_ = true;
365*eb293b8fSAndroid Build Coastguard Worker 
366*eb293b8fSAndroid Build Coastguard Worker   if (maps_ == nullptr) {
367*eb293b8fSAndroid Build Coastguard Worker     if (pid_ == getpid()) {
368*eb293b8fSAndroid Build Coastguard Worker       maps_ptr_.reset(new LocalMaps());
369*eb293b8fSAndroid Build Coastguard Worker     } else {
370*eb293b8fSAndroid Build Coastguard Worker       maps_ptr_.reset(new RemoteMaps(pid_));
371*eb293b8fSAndroid Build Coastguard Worker     }
372*eb293b8fSAndroid Build Coastguard Worker     if (!maps_ptr_->Parse()) {
373*eb293b8fSAndroid Build Coastguard Worker       ClearErrors();
374*eb293b8fSAndroid Build Coastguard Worker       last_error_.code = ERROR_INVALID_MAP;
375*eb293b8fSAndroid Build Coastguard Worker       return false;
376*eb293b8fSAndroid Build Coastguard Worker     }
377*eb293b8fSAndroid Build Coastguard Worker     maps_ = maps_ptr_.get();
378*eb293b8fSAndroid Build Coastguard Worker   }
379*eb293b8fSAndroid Build Coastguard Worker 
380*eb293b8fSAndroid Build Coastguard Worker   if (process_memory_ == nullptr) {
381*eb293b8fSAndroid Build Coastguard Worker     if (pid_ == getpid()) {
382*eb293b8fSAndroid Build Coastguard Worker       // Local unwind, so use thread cache to allow multiple threads
383*eb293b8fSAndroid Build Coastguard Worker       // to cache data even when multiple threads access the same object.
384*eb293b8fSAndroid Build Coastguard Worker       process_memory_ = Memory::CreateProcessMemoryThreadCached(pid_);
385*eb293b8fSAndroid Build Coastguard Worker     } else {
386*eb293b8fSAndroid Build Coastguard Worker       // Remote unwind should be safe to cache since the unwind will
387*eb293b8fSAndroid Build Coastguard Worker       // be occurring on a stopped process.
388*eb293b8fSAndroid Build Coastguard Worker       process_memory_ = Memory::CreateProcessMemoryCached(pid_);
389*eb293b8fSAndroid Build Coastguard Worker     }
390*eb293b8fSAndroid Build Coastguard Worker   }
391*eb293b8fSAndroid Build Coastguard Worker 
392*eb293b8fSAndroid Build Coastguard Worker   // jit_debug_ and dex_files_ may have already been set, for example in
393*eb293b8fSAndroid Build Coastguard Worker   // AndroidLocalUnwinder::InternalUnwind.
394*eb293b8fSAndroid Build Coastguard Worker   if (jit_debug_ == nullptr) {
395*eb293b8fSAndroid Build Coastguard Worker     jit_debug_ptr_ = CreateJitDebug(arch_, process_memory_);
396*eb293b8fSAndroid Build Coastguard Worker     SetJitDebug(jit_debug_ptr_.get());
397*eb293b8fSAndroid Build Coastguard Worker   }
398*eb293b8fSAndroid Build Coastguard Worker #if defined(DEXFILE_SUPPORT)
399*eb293b8fSAndroid Build Coastguard Worker   if (dex_files_ == nullptr) {
400*eb293b8fSAndroid Build Coastguard Worker     dex_files_ptr_ = CreateDexFiles(arch_, process_memory_);
401*eb293b8fSAndroid Build Coastguard Worker     SetDexFiles(dex_files_ptr_.get());
402*eb293b8fSAndroid Build Coastguard Worker   }
403*eb293b8fSAndroid Build Coastguard Worker #endif
404*eb293b8fSAndroid Build Coastguard Worker 
405*eb293b8fSAndroid Build Coastguard Worker   return true;
406*eb293b8fSAndroid Build Coastguard Worker }
407*eb293b8fSAndroid Build Coastguard Worker 
Unwind(const std::vector<std::string> * initial_map_names_to_skip,const std::vector<std::string> * map_suffixes_to_ignore)408*eb293b8fSAndroid Build Coastguard Worker void UnwinderFromPid::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
409*eb293b8fSAndroid Build Coastguard Worker                              const std::vector<std::string>* map_suffixes_to_ignore) {
410*eb293b8fSAndroid Build Coastguard Worker   if (!Init()) {
411*eb293b8fSAndroid Build Coastguard Worker     return;
412*eb293b8fSAndroid Build Coastguard Worker   }
413*eb293b8fSAndroid Build Coastguard Worker   Unwinder::Unwind(initial_map_names_to_skip, map_suffixes_to_ignore);
414*eb293b8fSAndroid Build Coastguard Worker }
415*eb293b8fSAndroid Build Coastguard Worker 
BuildFrameFromPcOnly(uint64_t pc,ArchEnum arch,Maps * maps,JitDebug * jit_debug,std::shared_ptr<Memory> process_memory,bool resolve_names)416*eb293b8fSAndroid Build Coastguard Worker FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps,
417*eb293b8fSAndroid Build Coastguard Worker                                          JitDebug* jit_debug,
418*eb293b8fSAndroid Build Coastguard Worker                                          std::shared_ptr<Memory> process_memory,
419*eb293b8fSAndroid Build Coastguard Worker                                          bool resolve_names) {
420*eb293b8fSAndroid Build Coastguard Worker   FrameData frame;
421*eb293b8fSAndroid Build Coastguard Worker 
422*eb293b8fSAndroid Build Coastguard Worker   std::shared_ptr<MapInfo> map_info = maps->Find(pc);
423*eb293b8fSAndroid Build Coastguard Worker   if (map_info == nullptr || arch == ARCH_UNKNOWN) {
424*eb293b8fSAndroid Build Coastguard Worker     frame.pc = pc;
425*eb293b8fSAndroid Build Coastguard Worker     frame.rel_pc = pc;
426*eb293b8fSAndroid Build Coastguard Worker     return frame;
427*eb293b8fSAndroid Build Coastguard Worker   }
428*eb293b8fSAndroid Build Coastguard Worker 
429*eb293b8fSAndroid Build Coastguard Worker   Elf* elf = map_info->GetElf(process_memory, arch);
430*eb293b8fSAndroid Build Coastguard Worker 
431*eb293b8fSAndroid Build Coastguard Worker   uint64_t relative_pc = elf->GetRelPc(pc, map_info.get());
432*eb293b8fSAndroid Build Coastguard Worker 
433*eb293b8fSAndroid Build Coastguard Worker   uint64_t pc_adjustment = GetPcAdjustment(relative_pc, elf, arch);
434*eb293b8fSAndroid Build Coastguard Worker   relative_pc -= pc_adjustment;
435*eb293b8fSAndroid Build Coastguard Worker   // The debug PC may be different if the PC comes from the JIT.
436*eb293b8fSAndroid Build Coastguard Worker   uint64_t debug_pc = relative_pc;
437*eb293b8fSAndroid Build Coastguard Worker 
438*eb293b8fSAndroid Build Coastguard Worker   // If we don't have a valid ELF file, check the JIT.
439*eb293b8fSAndroid Build Coastguard Worker   if (!elf->valid() && jit_debug != nullptr) {
440*eb293b8fSAndroid Build Coastguard Worker     uint64_t jit_pc = pc - pc_adjustment;
441*eb293b8fSAndroid Build Coastguard Worker     Elf* jit_elf = jit_debug->Find(maps, jit_pc);
442*eb293b8fSAndroid Build Coastguard Worker     if (jit_elf != nullptr) {
443*eb293b8fSAndroid Build Coastguard Worker       debug_pc = jit_pc;
444*eb293b8fSAndroid Build Coastguard Worker       elf = jit_elf;
445*eb293b8fSAndroid Build Coastguard Worker     }
446*eb293b8fSAndroid Build Coastguard Worker   }
447*eb293b8fSAndroid Build Coastguard Worker 
448*eb293b8fSAndroid Build Coastguard Worker   // Copy all the things we need into the frame for symbolization.
449*eb293b8fSAndroid Build Coastguard Worker   frame.rel_pc = relative_pc;
450*eb293b8fSAndroid Build Coastguard Worker   frame.pc = pc - pc_adjustment;
451*eb293b8fSAndroid Build Coastguard Worker   frame.map_info = map_info;
452*eb293b8fSAndroid Build Coastguard Worker 
453*eb293b8fSAndroid Build Coastguard Worker   if (!resolve_names ||
454*eb293b8fSAndroid Build Coastguard Worker       !elf->GetFunctionName(debug_pc, &frame.function_name, &frame.function_offset)) {
455*eb293b8fSAndroid Build Coastguard Worker     frame.function_name = "";
456*eb293b8fSAndroid Build Coastguard Worker     frame.function_offset = 0;
457*eb293b8fSAndroid Build Coastguard Worker   }
458*eb293b8fSAndroid Build Coastguard Worker   return frame;
459*eb293b8fSAndroid Build Coastguard Worker }
460*eb293b8fSAndroid Build Coastguard Worker 
BuildFrameFromPcOnly(uint64_t pc)461*eb293b8fSAndroid Build Coastguard Worker FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc) {
462*eb293b8fSAndroid Build Coastguard Worker   return BuildFrameFromPcOnly(pc, arch_, maps_, jit_debug_, process_memory_, resolve_names_);
463*eb293b8fSAndroid Build Coastguard Worker }
464*eb293b8fSAndroid Build Coastguard Worker 
465*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
466