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