xref: /aosp_15_r20/system/unwinding/libunwindstack/utils/OfflineUnwindUtils.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2021 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 <err.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <errno.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <inttypes.h>
20*eb293b8fSAndroid Build Coastguard Worker #include <string.h>
21*eb293b8fSAndroid Build Coastguard Worker 
22*eb293b8fSAndroid Build Coastguard Worker #include <cstddef>
23*eb293b8fSAndroid Build Coastguard Worker #include <filesystem>
24*eb293b8fSAndroid Build Coastguard Worker #include <fstream>
25*eb293b8fSAndroid Build Coastguard Worker #include <iostream>
26*eb293b8fSAndroid Build Coastguard Worker #include <memory>
27*eb293b8fSAndroid Build Coastguard Worker #include <regex>
28*eb293b8fSAndroid Build Coastguard Worker #include <sstream>
29*eb293b8fSAndroid Build Coastguard Worker #include <string>
30*eb293b8fSAndroid Build Coastguard Worker #include <tuple>
31*eb293b8fSAndroid Build Coastguard Worker #include <utility>
32*eb293b8fSAndroid Build Coastguard Worker #include <vector>
33*eb293b8fSAndroid Build Coastguard Worker 
34*eb293b8fSAndroid Build Coastguard Worker #include <android-base/file.h>
35*eb293b8fSAndroid Build Coastguard Worker #include <android-base/strings.h>
36*eb293b8fSAndroid Build Coastguard Worker #include <zlib.h>
37*eb293b8fSAndroid Build Coastguard Worker 
38*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Arch.h>
39*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/JitDebug.h>
40*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineArm.h>
41*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineArm64.h>
42*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineRiscv64.h>
43*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineX86.h>
44*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MachineX86_64.h>
45*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
46*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Regs.h>
47*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsArm.h>
48*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsArm64.h>
49*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsRiscv64.h>
50*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsX86.h>
51*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsX86_64.h>
52*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h>
53*eb293b8fSAndroid Build Coastguard Worker 
54*eb293b8fSAndroid Build Coastguard Worker #include "Check.h"
55*eb293b8fSAndroid Build Coastguard Worker #include "MemoryOffline.h"
56*eb293b8fSAndroid Build Coastguard Worker #include "utils/MemoryFake.h"
57*eb293b8fSAndroid Build Coastguard Worker 
58*eb293b8fSAndroid Build Coastguard Worker #include "OfflineUnwindUtils.h"
59*eb293b8fSAndroid Build Coastguard Worker 
60*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
61*eb293b8fSAndroid Build Coastguard Worker 
DecompressFiles(const std::string & directory)62*eb293b8fSAndroid Build Coastguard Worker void DecompressFiles(const std::string& directory) {
63*eb293b8fSAndroid Build Coastguard Worker   namespace fs = std::filesystem;
64*eb293b8fSAndroid Build Coastguard Worker   for (const auto& file : fs::recursive_directory_iterator(directory)) {
65*eb293b8fSAndroid Build Coastguard Worker     fs::path src_path = file.path();
66*eb293b8fSAndroid Build Coastguard Worker     if (src_path.extension() == ".gz") {
67*eb293b8fSAndroid Build Coastguard Worker       fs::path dst_path = fs::path(src_path).replace_extension();  // Remove .gz extension.
68*eb293b8fSAndroid Build Coastguard Worker       if (!fs::exists(dst_path) || fs::last_write_time(src_path) > fs::last_write_time(dst_path)) {
69*eb293b8fSAndroid Build Coastguard Worker         gzFile src = gzopen(src_path.c_str(), "rb");
70*eb293b8fSAndroid Build Coastguard Worker         CHECK(src != nullptr);
71*eb293b8fSAndroid Build Coastguard Worker         fs::path tmp_path = fs::path(src_path).replace_extension("." + std::to_string(getpid()));
72*eb293b8fSAndroid Build Coastguard Worker         std::ofstream tmp(tmp_path);  // Temporary file to avoid races between unit tests.
73*eb293b8fSAndroid Build Coastguard Worker         char buffer[1024];
74*eb293b8fSAndroid Build Coastguard Worker         int size;
75*eb293b8fSAndroid Build Coastguard Worker         while ((size = gzread(src, buffer, sizeof(buffer))) > 0) {
76*eb293b8fSAndroid Build Coastguard Worker           tmp.write(buffer, size);
77*eb293b8fSAndroid Build Coastguard Worker         }
78*eb293b8fSAndroid Build Coastguard Worker         tmp.close();
79*eb293b8fSAndroid Build Coastguard Worker         gzclose(src);
80*eb293b8fSAndroid Build Coastguard Worker         fs::rename(tmp_path, dst_path);
81*eb293b8fSAndroid Build Coastguard Worker       }
82*eb293b8fSAndroid Build Coastguard Worker     }
83*eb293b8fSAndroid Build Coastguard Worker   }
84*eb293b8fSAndroid Build Coastguard Worker }
85*eb293b8fSAndroid Build Coastguard Worker 
CreateLinks(const std::string & directory)86*eb293b8fSAndroid Build Coastguard Worker void CreateLinks(const std::string& directory) {
87*eb293b8fSAndroid Build Coastguard Worker   namespace fs = std::filesystem;
88*eb293b8fSAndroid Build Coastguard Worker   for (const auto& file : fs::recursive_directory_iterator(directory)) {
89*eb293b8fSAndroid Build Coastguard Worker     fs::path src_path = file.path();
90*eb293b8fSAndroid Build Coastguard Worker     if (fs::is_regular_file(src_path) && src_path.filename() == "links.txt") {
91*eb293b8fSAndroid Build Coastguard Worker       std::string contents;
92*eb293b8fSAndroid Build Coastguard Worker       if (!android::base::ReadFileToString(src_path.c_str(), &contents)) {
93*eb293b8fSAndroid Build Coastguard Worker         errx(1, "Unable to read file: %s", src_path.c_str());
94*eb293b8fSAndroid Build Coastguard Worker       }
95*eb293b8fSAndroid Build Coastguard Worker       fs::path parent_path = src_path.parent_path();
96*eb293b8fSAndroid Build Coastguard Worker       std::vector<std::string> lines(android::base::Split(contents, "\n"));
97*eb293b8fSAndroid Build Coastguard Worker       for (auto line : lines) {
98*eb293b8fSAndroid Build Coastguard Worker         std::string trimmed_line(android::base::Trim(line));
99*eb293b8fSAndroid Build Coastguard Worker         if (trimmed_line.empty()) {
100*eb293b8fSAndroid Build Coastguard Worker           continue;
101*eb293b8fSAndroid Build Coastguard Worker         }
102*eb293b8fSAndroid Build Coastguard Worker 
103*eb293b8fSAndroid Build Coastguard Worker         std::vector<std::string> values(android::base::Split(trimmed_line, " "));
104*eb293b8fSAndroid Build Coastguard Worker         if (values.size() != 2) {
105*eb293b8fSAndroid Build Coastguard Worker           errx(1, "Invalid line in %s: line %s", src_path.c_str(), line.c_str());
106*eb293b8fSAndroid Build Coastguard Worker         }
107*eb293b8fSAndroid Build Coastguard Worker 
108*eb293b8fSAndroid Build Coastguard Worker         // Create the symlink if it doesn't already exist.
109*eb293b8fSAndroid Build Coastguard Worker         fs::path target(parent_path);
110*eb293b8fSAndroid Build Coastguard Worker         target /= fs::path(values[0]);
111*eb293b8fSAndroid Build Coastguard Worker         fs::path source(parent_path);
112*eb293b8fSAndroid Build Coastguard Worker         source /= fs::path(values[1]);
113*eb293b8fSAndroid Build Coastguard Worker         if (!fs::exists(source)) {
114*eb293b8fSAndroid Build Coastguard Worker           // Ignore any errors, if this is running at the same time
115*eb293b8fSAndroid Build Coastguard Worker           // in multiple processes, then this might fail.
116*eb293b8fSAndroid Build Coastguard Worker           std::error_code ec;
117*eb293b8fSAndroid Build Coastguard Worker           fs::create_symlink(target, source, ec);
118*eb293b8fSAndroid Build Coastguard Worker         }
119*eb293b8fSAndroid Build Coastguard Worker       }
120*eb293b8fSAndroid Build Coastguard Worker     }
121*eb293b8fSAndroid Build Coastguard Worker   }
122*eb293b8fSAndroid Build Coastguard Worker }
123*eb293b8fSAndroid Build Coastguard Worker 
GetOfflineFilesDirectory()124*eb293b8fSAndroid Build Coastguard Worker std::string GetOfflineFilesDirectory() {
125*eb293b8fSAndroid Build Coastguard Worker   std::string path = android::base::GetExecutableDirectory() + "/offline_files/";
126*eb293b8fSAndroid Build Coastguard Worker   DecompressFiles(path);
127*eb293b8fSAndroid Build Coastguard Worker   CreateLinks(path);
128*eb293b8fSAndroid Build Coastguard Worker   return path;
129*eb293b8fSAndroid Build Coastguard Worker }
130*eb293b8fSAndroid Build Coastguard Worker 
DumpFrames(const Unwinder & unwinder)131*eb293b8fSAndroid Build Coastguard Worker std::string DumpFrames(const Unwinder& unwinder) {
132*eb293b8fSAndroid Build Coastguard Worker   std::string str;
133*eb293b8fSAndroid Build Coastguard Worker   for (size_t i = 0; i < unwinder.NumFrames(); i++) {
134*eb293b8fSAndroid Build Coastguard Worker     str += unwinder.FormatFrame(i) + "\n";
135*eb293b8fSAndroid Build Coastguard Worker   }
136*eb293b8fSAndroid Build Coastguard Worker   return str;
137*eb293b8fSAndroid Build Coastguard Worker }
138*eb293b8fSAndroid Build Coastguard Worker 
AddMemory(std::string file_name,MemoryOfflineParts * parts,std::string * error_msg)139*eb293b8fSAndroid Build Coastguard Worker bool AddMemory(std::string file_name, MemoryOfflineParts* parts, std::string* error_msg) {
140*eb293b8fSAndroid Build Coastguard Worker   MemoryOffline* memory = new MemoryOffline;
141*eb293b8fSAndroid Build Coastguard Worker   if (!memory->Init(file_name.c_str(), 0)) {
142*eb293b8fSAndroid Build Coastguard Worker     std::stringstream err_stream;
143*eb293b8fSAndroid Build Coastguard Worker     err_stream << "Failed to add stack '" << file_name << "' to stack memory.";
144*eb293b8fSAndroid Build Coastguard Worker     *error_msg = err_stream.str();
145*eb293b8fSAndroid Build Coastguard Worker     return false;
146*eb293b8fSAndroid Build Coastguard Worker   }
147*eb293b8fSAndroid Build Coastguard Worker   parts->Add(memory);
148*eb293b8fSAndroid Build Coastguard Worker 
149*eb293b8fSAndroid Build Coastguard Worker   return true;
150*eb293b8fSAndroid Build Coastguard Worker }
151*eb293b8fSAndroid Build Coastguard Worker 
GetRegs(const std::string & initial_sample_name) const152*eb293b8fSAndroid Build Coastguard Worker Regs* OfflineUnwindUtils::GetRegs(const std::string& initial_sample_name) const {
153*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
154*eb293b8fSAndroid Build Coastguard Worker   std::string error_msg;
155*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, &error_msg)) {
156*eb293b8fSAndroid Build Coastguard Worker     std::cerr << error_msg;
157*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
158*eb293b8fSAndroid Build Coastguard Worker   }
159*eb293b8fSAndroid Build Coastguard Worker   return samples_.at(sample_name).regs.get();
160*eb293b8fSAndroid Build Coastguard Worker }
161*eb293b8fSAndroid Build Coastguard Worker 
GetMaps(const std::string & initial_sample_name) const162*eb293b8fSAndroid Build Coastguard Worker Maps* OfflineUnwindUtils::GetMaps(const std::string& initial_sample_name) const {
163*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
164*eb293b8fSAndroid Build Coastguard Worker   std::string error_msg;
165*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, &error_msg)) {
166*eb293b8fSAndroid Build Coastguard Worker     std::cerr << error_msg;
167*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
168*eb293b8fSAndroid Build Coastguard Worker   }
169*eb293b8fSAndroid Build Coastguard Worker   return samples_.at(sample_name).maps.get();
170*eb293b8fSAndroid Build Coastguard Worker }
171*eb293b8fSAndroid Build Coastguard Worker 
GetProcessMemory(const std::string & initial_sample_name) const172*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> OfflineUnwindUtils::GetProcessMemory(
173*eb293b8fSAndroid Build Coastguard Worker     const std::string& initial_sample_name) const {
174*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
175*eb293b8fSAndroid Build Coastguard Worker   std::string error_msg;
176*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, &error_msg)) {
177*eb293b8fSAndroid Build Coastguard Worker     std::cerr << error_msg;
178*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
179*eb293b8fSAndroid Build Coastguard Worker   }
180*eb293b8fSAndroid Build Coastguard Worker   return samples_.at(sample_name).process_memory;
181*eb293b8fSAndroid Build Coastguard Worker }
182*eb293b8fSAndroid Build Coastguard Worker 
GetJitDebug(const std::string & initial_sample_name) const183*eb293b8fSAndroid Build Coastguard Worker JitDebug* OfflineUnwindUtils::GetJitDebug(const std::string& initial_sample_name) const {
184*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
185*eb293b8fSAndroid Build Coastguard Worker   std::string error_msg;
186*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, &error_msg)) {
187*eb293b8fSAndroid Build Coastguard Worker     std::cerr << error_msg;
188*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
189*eb293b8fSAndroid Build Coastguard Worker   }
190*eb293b8fSAndroid Build Coastguard Worker   return samples_.at(sample_name).jit_debug.get();
191*eb293b8fSAndroid Build Coastguard Worker }
192*eb293b8fSAndroid Build Coastguard Worker 
GetOfflineFilesPath(const std::string & initial_sample_name) const193*eb293b8fSAndroid Build Coastguard Worker const std::string* OfflineUnwindUtils::GetOfflineFilesPath(
194*eb293b8fSAndroid Build Coastguard Worker     const std::string& initial_sample_name) const {
195*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
196*eb293b8fSAndroid Build Coastguard Worker   std::string error_msg;
197*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, &error_msg)) {
198*eb293b8fSAndroid Build Coastguard Worker     std::cerr << error_msg;
199*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
200*eb293b8fSAndroid Build Coastguard Worker   }
201*eb293b8fSAndroid Build Coastguard Worker   return &samples_.at(sample_name).offline_files_path;
202*eb293b8fSAndroid Build Coastguard Worker }
203*eb293b8fSAndroid Build Coastguard Worker 
GetFrameInfoFilepath(const std::string & initial_sample_name) const204*eb293b8fSAndroid Build Coastguard Worker const std::string* OfflineUnwindUtils::GetFrameInfoFilepath(
205*eb293b8fSAndroid Build Coastguard Worker     const std::string& initial_sample_name) const {
206*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
207*eb293b8fSAndroid Build Coastguard Worker   std::string error_msg;
208*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, &error_msg)) {
209*eb293b8fSAndroid Build Coastguard Worker     std::cerr << error_msg;
210*eb293b8fSAndroid Build Coastguard Worker     return nullptr;
211*eb293b8fSAndroid Build Coastguard Worker   }
212*eb293b8fSAndroid Build Coastguard Worker   return &samples_.at(sample_name).frame_info_filepath;
213*eb293b8fSAndroid Build Coastguard Worker }
214*eb293b8fSAndroid Build Coastguard Worker 
Init(const std::vector<UnwindSampleInfo> & sample_infos,std::string * error_msg)215*eb293b8fSAndroid Build Coastguard Worker bool OfflineUnwindUtils::Init(const std::vector<UnwindSampleInfo>& sample_infos,
216*eb293b8fSAndroid Build Coastguard Worker                               std::string* error_msg) {
217*eb293b8fSAndroid Build Coastguard Worker   // Save the current path so the caller can switch back to it later.
218*eb293b8fSAndroid Build Coastguard Worker   cwd_ = std::filesystem::current_path();
219*eb293b8fSAndroid Build Coastguard Worker 
220*eb293b8fSAndroid Build Coastguard Worker   // Fill in the unwind samples.
221*eb293b8fSAndroid Build Coastguard Worker   std::stringstream err_stream;
222*eb293b8fSAndroid Build Coastguard Worker   for (const auto& sample_info : sample_infos) {
223*eb293b8fSAndroid Build Coastguard Worker     std::string offline_files_full_path =
224*eb293b8fSAndroid Build Coastguard Worker         GetOfflineFilesDirectory() + sample_info.offline_files_dir;
225*eb293b8fSAndroid Build Coastguard Worker     if (!std::filesystem::exists(offline_files_full_path)) {
226*eb293b8fSAndroid Build Coastguard Worker       err_stream << "Offline files directory '" << offline_files_full_path << "' does not exist.";
227*eb293b8fSAndroid Build Coastguard Worker       *error_msg = err_stream.str();
228*eb293b8fSAndroid Build Coastguard Worker       return false;
229*eb293b8fSAndroid Build Coastguard Worker     }
230*eb293b8fSAndroid Build Coastguard Worker     std::string frame_info_filepath = offline_files_full_path + sample_info.frame_info_filename;
231*eb293b8fSAndroid Build Coastguard Worker 
232*eb293b8fSAndroid Build Coastguard Worker     std::string map_buffer;
233*eb293b8fSAndroid Build Coastguard Worker     if (!android::base::ReadFileToString((offline_files_full_path + "maps.txt"), &map_buffer)) {
234*eb293b8fSAndroid Build Coastguard Worker       err_stream << "Failed to read from '" << offline_files_full_path << "maps.txt' into memory.";
235*eb293b8fSAndroid Build Coastguard Worker       *error_msg = err_stream.str();
236*eb293b8fSAndroid Build Coastguard Worker       return false;
237*eb293b8fSAndroid Build Coastguard Worker     }
238*eb293b8fSAndroid Build Coastguard Worker 
239*eb293b8fSAndroid Build Coastguard Worker     // CreateMaps, CreatRegs, and Create*Memory may need to be called later by the client. So we
240*eb293b8fSAndroid Build Coastguard Worker     // need to create the sample now in case the flags are set to call these methods in Init.
241*eb293b8fSAndroid Build Coastguard Worker     const std::string& sample_name = sample_info.offline_files_dir;
242*eb293b8fSAndroid Build Coastguard Worker     samples_.emplace(sample_name, (UnwindSample){
243*eb293b8fSAndroid Build Coastguard Worker                                       std::move(offline_files_full_path),
244*eb293b8fSAndroid Build Coastguard Worker                                       std::move(frame_info_filepath), std::move(map_buffer),
245*eb293b8fSAndroid Build Coastguard Worker                                       nullptr,                         // regs
246*eb293b8fSAndroid Build Coastguard Worker                                       nullptr,                         // maps
247*eb293b8fSAndroid Build Coastguard Worker                                       std::make_shared<MemoryFake>(),  // process_memory
248*eb293b8fSAndroid Build Coastguard Worker                                       nullptr,                         // jit_debug
249*eb293b8fSAndroid Build Coastguard Worker                                   });
250*eb293b8fSAndroid Build Coastguard Worker     UnwindSample& sample = samples_.at(sample_name);
251*eb293b8fSAndroid Build Coastguard Worker 
252*eb293b8fSAndroid Build Coastguard Worker     if (sample_info.create_maps) {
253*eb293b8fSAndroid Build Coastguard Worker       if (!CreateMaps(error_msg, sample_name)) return false;
254*eb293b8fSAndroid Build Coastguard Worker     }
255*eb293b8fSAndroid Build Coastguard Worker     if (!CreateRegs(sample_info.arch, error_msg, sample_name)) return false;
256*eb293b8fSAndroid Build Coastguard Worker 
257*eb293b8fSAndroid Build Coastguard Worker     switch (sample_info.memory_flag) {
258*eb293b8fSAndroid Build Coastguard Worker       case ProcessMemoryFlag::kNone: {
259*eb293b8fSAndroid Build Coastguard Worker         if (!CreateProcessMemory(error_msg, sample_name)) return false;
260*eb293b8fSAndroid Build Coastguard Worker         break;
261*eb293b8fSAndroid Build Coastguard Worker       }
262*eb293b8fSAndroid Build Coastguard Worker       case ProcessMemoryFlag::kIncludeJitMemory: {
263*eb293b8fSAndroid Build Coastguard Worker         if (!CreateProcessMemory(error_msg, sample_name)) return false;
264*eb293b8fSAndroid Build Coastguard Worker         sample.jit_debug = CreateJitDebug(sample.regs->Arch(), sample.process_memory);
265*eb293b8fSAndroid Build Coastguard Worker         break;
266*eb293b8fSAndroid Build Coastguard Worker       }
267*eb293b8fSAndroid Build Coastguard Worker       case ProcessMemoryFlag::kNoMemory: {
268*eb293b8fSAndroid Build Coastguard Worker         break;
269*eb293b8fSAndroid Build Coastguard Worker       }
270*eb293b8fSAndroid Build Coastguard Worker       default: {
271*eb293b8fSAndroid Build Coastguard Worker         std::stringstream err_stream;
272*eb293b8fSAndroid Build Coastguard Worker         err_stream << "Unknown memory type for sample '" << sample_name << "'.";
273*eb293b8fSAndroid Build Coastguard Worker         *error_msg = err_stream.str();
274*eb293b8fSAndroid Build Coastguard Worker         return false;
275*eb293b8fSAndroid Build Coastguard Worker       }
276*eb293b8fSAndroid Build Coastguard Worker     }
277*eb293b8fSAndroid Build Coastguard Worker   }
278*eb293b8fSAndroid Build Coastguard Worker   initted_ = true;
279*eb293b8fSAndroid Build Coastguard Worker   return true;
280*eb293b8fSAndroid Build Coastguard Worker }
281*eb293b8fSAndroid Build Coastguard Worker 
Init(const UnwindSampleInfo & sample_info,std::string * error_msg)282*eb293b8fSAndroid Build Coastguard Worker bool OfflineUnwindUtils::Init(const UnwindSampleInfo& sample_info, std::string* error_msg) {
283*eb293b8fSAndroid Build Coastguard Worker   if (Init(std::vector<UnwindSampleInfo>{sample_info}, error_msg)) {
284*eb293b8fSAndroid Build Coastguard Worker     if (!ChangeToSampleDirectory(error_msg)) return false;
285*eb293b8fSAndroid Build Coastguard Worker     return true;
286*eb293b8fSAndroid Build Coastguard Worker   }
287*eb293b8fSAndroid Build Coastguard Worker   return false;
288*eb293b8fSAndroid Build Coastguard Worker }
289*eb293b8fSAndroid Build Coastguard Worker 
ChangeToSampleDirectory(std::string * error_msg,const std::string & initial_sample_name) const290*eb293b8fSAndroid Build Coastguard Worker bool OfflineUnwindUtils::ChangeToSampleDirectory(std::string* error_msg,
291*eb293b8fSAndroid Build Coastguard Worker                                                  const std::string& initial_sample_name) const {
292*eb293b8fSAndroid Build Coastguard Worker   if (!initted_) {
293*eb293b8fSAndroid Build Coastguard Worker     *error_msg =
294*eb293b8fSAndroid Build Coastguard Worker         "Cannot change to sample directory because OfflineUnwindUtils::Init has not been called.";
295*eb293b8fSAndroid Build Coastguard Worker     return false;
296*eb293b8fSAndroid Build Coastguard Worker   }
297*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
298*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, error_msg)) return false;
299*eb293b8fSAndroid Build Coastguard Worker 
300*eb293b8fSAndroid Build Coastguard Worker   std::filesystem::current_path(std::filesystem::path(samples_.at(sample_name).offline_files_path));
301*eb293b8fSAndroid Build Coastguard Worker   return true;
302*eb293b8fSAndroid Build Coastguard Worker }
303*eb293b8fSAndroid Build Coastguard Worker 
GetExpectedNumFrames(size_t * expected_num_frames,std::string * error_msg,const std::string & initial_sample_name) const304*eb293b8fSAndroid Build Coastguard Worker bool OfflineUnwindUtils::GetExpectedNumFrames(size_t* expected_num_frames, std::string* error_msg,
305*eb293b8fSAndroid Build Coastguard Worker                                               const std::string& initial_sample_name) const {
306*eb293b8fSAndroid Build Coastguard Worker   if (!initted_) {
307*eb293b8fSAndroid Build Coastguard Worker     *error_msg =
308*eb293b8fSAndroid Build Coastguard Worker         "Cannot get expected number of frames of a sample because OfflineUnwindUtils::Init has not "
309*eb293b8fSAndroid Build Coastguard Worker         "been called.";
310*eb293b8fSAndroid Build Coastguard Worker     return false;
311*eb293b8fSAndroid Build Coastguard Worker   }
312*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
313*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, error_msg)) return false;
314*eb293b8fSAndroid Build Coastguard Worker 
315*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_frames_path = samples_.at(sample_name).frame_info_filepath;
316*eb293b8fSAndroid Build Coastguard Worker   if (!std::filesystem::exists(sample_frames_path)) {
317*eb293b8fSAndroid Build Coastguard Worker     std::stringstream err_stream;
318*eb293b8fSAndroid Build Coastguard Worker     err_stream << "Offline files directory '" << sample_frames_path << "' does not exist.";
319*eb293b8fSAndroid Build Coastguard Worker     *error_msg = err_stream.str();
320*eb293b8fSAndroid Build Coastguard Worker     return false;
321*eb293b8fSAndroid Build Coastguard Worker   }
322*eb293b8fSAndroid Build Coastguard Worker 
323*eb293b8fSAndroid Build Coastguard Worker   std::ifstream in(sample_frames_path);
324*eb293b8fSAndroid Build Coastguard Worker   in.unsetf(std::ios_base::skipws);  // Ensure that we do not skip newlines.
325*eb293b8fSAndroid Build Coastguard Worker   *expected_num_frames =
326*eb293b8fSAndroid Build Coastguard Worker       std::count(std::istream_iterator<char>(in), std::istream_iterator<char>(), '\n');
327*eb293b8fSAndroid Build Coastguard Worker 
328*eb293b8fSAndroid Build Coastguard Worker   return true;
329*eb293b8fSAndroid Build Coastguard Worker }
330*eb293b8fSAndroid Build Coastguard Worker 
CreateMaps(std::string * error_msg,const std::string & initial_sample_name)331*eb293b8fSAndroid Build Coastguard Worker bool OfflineUnwindUtils::CreateMaps(std::string* error_msg,
332*eb293b8fSAndroid Build Coastguard Worker                                     const std::string& initial_sample_name) {
333*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
334*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, error_msg)) return false;
335*eb293b8fSAndroid Build Coastguard Worker   UnwindSample& sample = samples_.at(sample_name);
336*eb293b8fSAndroid Build Coastguard Worker 
337*eb293b8fSAndroid Build Coastguard Worker   sample.maps.reset(new BufferMaps(sample.map_buffer.c_str()));
338*eb293b8fSAndroid Build Coastguard Worker   if (!sample.maps->Parse()) {
339*eb293b8fSAndroid Build Coastguard Worker     *error_msg = "Failed to parse offline maps.";
340*eb293b8fSAndroid Build Coastguard Worker     return false;
341*eb293b8fSAndroid Build Coastguard Worker   }
342*eb293b8fSAndroid Build Coastguard Worker   return true;
343*eb293b8fSAndroid Build Coastguard Worker }
344*eb293b8fSAndroid Build Coastguard Worker 
CreateProcessMemory(std::string * error_msg,const std::string & initial_sample_name)345*eb293b8fSAndroid Build Coastguard Worker bool OfflineUnwindUtils::CreateProcessMemory(std::string* error_msg,
346*eb293b8fSAndroid Build Coastguard Worker                                              const std::string& initial_sample_name) {
347*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
348*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, error_msg)) return false;
349*eb293b8fSAndroid Build Coastguard Worker   UnwindSample& sample = samples_.at(sample_name);
350*eb293b8fSAndroid Build Coastguard Worker 
351*eb293b8fSAndroid Build Coastguard Worker   // Construct process memory from all descriptor, stack, entry, and jit files
352*eb293b8fSAndroid Build Coastguard Worker   auto memory = std::make_unique<MemoryOfflineParts>();
353*eb293b8fSAndroid Build Coastguard Worker   bool data_files_found = false;
354*eb293b8fSAndroid Build Coastguard Worker   for (const auto& file : std::filesystem::directory_iterator(sample.offline_files_path)) {
355*eb293b8fSAndroid Build Coastguard Worker     std::string filename = file.path().string();
356*eb293b8fSAndroid Build Coastguard Worker     if (std::regex_match(filename,
357*eb293b8fSAndroid Build Coastguard Worker                          std::regex("^(.+)\\/(descriptor|stack|entry|jit)(\\d*)\\.data$"))) {
358*eb293b8fSAndroid Build Coastguard Worker       data_files_found = true;
359*eb293b8fSAndroid Build Coastguard Worker       if (!AddMemory(filename, memory.get(), error_msg)) return false;
360*eb293b8fSAndroid Build Coastguard Worker     }
361*eb293b8fSAndroid Build Coastguard Worker   }
362*eb293b8fSAndroid Build Coastguard Worker   if (!data_files_found) {
363*eb293b8fSAndroid Build Coastguard Worker     *error_msg = "No memory (stack, JIT, etc.) data files found.";
364*eb293b8fSAndroid Build Coastguard Worker     return false;
365*eb293b8fSAndroid Build Coastguard Worker   }
366*eb293b8fSAndroid Build Coastguard Worker 
367*eb293b8fSAndroid Build Coastguard Worker   sample.process_memory.reset(memory.release());
368*eb293b8fSAndroid Build Coastguard Worker   return true;
369*eb293b8fSAndroid Build Coastguard Worker }
370*eb293b8fSAndroid Build Coastguard Worker 
371*eb293b8fSAndroid Build Coastguard Worker namespace {
372*eb293b8fSAndroid Build Coastguard Worker template <typename AddressType>
ReadRegs(RegsImpl<AddressType> * regs,const std::unordered_map<std::string,uint32_t> & name_to_reg,std::string * error_msg,const std::string & offline_files_path)373*eb293b8fSAndroid Build Coastguard Worker bool ReadRegs(RegsImpl<AddressType>* regs,
374*eb293b8fSAndroid Build Coastguard Worker               const std::unordered_map<std::string, uint32_t>& name_to_reg, std::string* error_msg,
375*eb293b8fSAndroid Build Coastguard Worker               const std::string& offline_files_path) {
376*eb293b8fSAndroid Build Coastguard Worker   std::stringstream err_stream;
377*eb293b8fSAndroid Build Coastguard Worker   FILE* fp = fopen((offline_files_path + "regs.txt").c_str(), "r");
378*eb293b8fSAndroid Build Coastguard Worker   if (fp == nullptr) {
379*eb293b8fSAndroid Build Coastguard Worker     err_stream << "Error opening file '" << offline_files_path << "regs.txt': " << strerror(errno);
380*eb293b8fSAndroid Build Coastguard Worker     *error_msg = err_stream.str();
381*eb293b8fSAndroid Build Coastguard Worker     return false;
382*eb293b8fSAndroid Build Coastguard Worker   }
383*eb293b8fSAndroid Build Coastguard Worker 
384*eb293b8fSAndroid Build Coastguard Worker   while (!feof(fp)) {
385*eb293b8fSAndroid Build Coastguard Worker     uint64_t value;
386*eb293b8fSAndroid Build Coastguard Worker     char reg_name[100];
387*eb293b8fSAndroid Build Coastguard Worker     if (fscanf(fp, "%[^:]: %" SCNx64 "\n", reg_name, &value) != 2) {
388*eb293b8fSAndroid Build Coastguard Worker       err_stream << "Failed to read in register name/values from '" << offline_files_path
389*eb293b8fSAndroid Build Coastguard Worker                  << "regs.txt'.";
390*eb293b8fSAndroid Build Coastguard Worker       *error_msg = err_stream.str();
391*eb293b8fSAndroid Build Coastguard Worker       return false;
392*eb293b8fSAndroid Build Coastguard Worker     }
393*eb293b8fSAndroid Build Coastguard Worker     std::string name(reg_name);
394*eb293b8fSAndroid Build Coastguard Worker     auto entry = name_to_reg.find(name);
395*eb293b8fSAndroid Build Coastguard Worker     if (entry == name_to_reg.end()) {
396*eb293b8fSAndroid Build Coastguard Worker       err_stream << "Unknown register named " << name;
397*eb293b8fSAndroid Build Coastguard Worker       *error_msg = err_stream.str();
398*eb293b8fSAndroid Build Coastguard Worker       return false;
399*eb293b8fSAndroid Build Coastguard Worker     }
400*eb293b8fSAndroid Build Coastguard Worker     (*regs)[entry->second] = value;
401*eb293b8fSAndroid Build Coastguard Worker   }
402*eb293b8fSAndroid Build Coastguard Worker   fclose(fp);
403*eb293b8fSAndroid Build Coastguard Worker   return true;
404*eb293b8fSAndroid Build Coastguard Worker }
405*eb293b8fSAndroid Build Coastguard Worker }  // namespace
406*eb293b8fSAndroid Build Coastguard Worker 
CreateRegs(ArchEnum arch,std::string * error_msg,const std::string & initial_sample_name)407*eb293b8fSAndroid Build Coastguard Worker bool OfflineUnwindUtils::CreateRegs(ArchEnum arch, std::string* error_msg,
408*eb293b8fSAndroid Build Coastguard Worker                                     const std::string& initial_sample_name) {
409*eb293b8fSAndroid Build Coastguard Worker   const std::string& sample_name = GetAdjustedSampleName(initial_sample_name);
410*eb293b8fSAndroid Build Coastguard Worker   if (!IsValidUnwindSample(sample_name, error_msg)) return false;
411*eb293b8fSAndroid Build Coastguard Worker   auto& regs = samples_.at(sample_name).regs;
412*eb293b8fSAndroid Build Coastguard Worker   const auto& offline_files_path = samples_.at(sample_name).offline_files_path;
413*eb293b8fSAndroid Build Coastguard Worker 
414*eb293b8fSAndroid Build Coastguard Worker   switch (arch) {
415*eb293b8fSAndroid Build Coastguard Worker     case ARCH_ARM: {
416*eb293b8fSAndroid Build Coastguard Worker       RegsArm* regs_impl = new RegsArm;
417*eb293b8fSAndroid Build Coastguard Worker       regs.reset(regs_impl);
418*eb293b8fSAndroid Build Coastguard Worker       if (!ReadRegs<uint32_t>(regs_impl, arm_regs_, error_msg, offline_files_path)) return false;
419*eb293b8fSAndroid Build Coastguard Worker       break;
420*eb293b8fSAndroid Build Coastguard Worker     }
421*eb293b8fSAndroid Build Coastguard Worker     case ARCH_ARM64: {
422*eb293b8fSAndroid Build Coastguard Worker       RegsArm64* regs_impl = new RegsArm64;
423*eb293b8fSAndroid Build Coastguard Worker       regs.reset(regs_impl);
424*eb293b8fSAndroid Build Coastguard Worker       if (!ReadRegs<uint64_t>(regs_impl, arm64_regs_, error_msg, offline_files_path)) return false;
425*eb293b8fSAndroid Build Coastguard Worker       break;
426*eb293b8fSAndroid Build Coastguard Worker     }
427*eb293b8fSAndroid Build Coastguard Worker     case ARCH_RISCV64: {
428*eb293b8fSAndroid Build Coastguard Worker       RegsRiscv64* regs_impl = new RegsRiscv64;
429*eb293b8fSAndroid Build Coastguard Worker       regs.reset(regs_impl);
430*eb293b8fSAndroid Build Coastguard Worker       if (!ReadRegs<uint64_t>(regs_impl, riscv64_regs_, error_msg, offline_files_path))
431*eb293b8fSAndroid Build Coastguard Worker         return false;
432*eb293b8fSAndroid Build Coastguard Worker       break;
433*eb293b8fSAndroid Build Coastguard Worker     }
434*eb293b8fSAndroid Build Coastguard Worker     case ARCH_X86: {
435*eb293b8fSAndroid Build Coastguard Worker       RegsX86* regs_impl = new RegsX86;
436*eb293b8fSAndroid Build Coastguard Worker       regs.reset(regs_impl);
437*eb293b8fSAndroid Build Coastguard Worker       if (!ReadRegs<uint32_t>(regs_impl, x86_regs_, error_msg, offline_files_path)) return false;
438*eb293b8fSAndroid Build Coastguard Worker       break;
439*eb293b8fSAndroid Build Coastguard Worker     }
440*eb293b8fSAndroid Build Coastguard Worker     case ARCH_X86_64: {
441*eb293b8fSAndroid Build Coastguard Worker       RegsX86_64* regs_impl = new RegsX86_64;
442*eb293b8fSAndroid Build Coastguard Worker       regs.reset(regs_impl);
443*eb293b8fSAndroid Build Coastguard Worker       if (!ReadRegs<uint64_t>(regs_impl, x86_64_regs_, error_msg, offline_files_path)) return false;
444*eb293b8fSAndroid Build Coastguard Worker       break;
445*eb293b8fSAndroid Build Coastguard Worker     }
446*eb293b8fSAndroid Build Coastguard Worker     default:
447*eb293b8fSAndroid Build Coastguard Worker       *error_msg = "Unknown architechture " + std::to_string(arch);
448*eb293b8fSAndroid Build Coastguard Worker       return false;
449*eb293b8fSAndroid Build Coastguard Worker   }
450*eb293b8fSAndroid Build Coastguard Worker 
451*eb293b8fSAndroid Build Coastguard Worker   return true;
452*eb293b8fSAndroid Build Coastguard Worker }
453*eb293b8fSAndroid Build Coastguard Worker 
GetAdjustedSampleName(const std::string & initial_sample_name) const454*eb293b8fSAndroid Build Coastguard Worker const std::string& OfflineUnwindUtils::GetAdjustedSampleName(
455*eb293b8fSAndroid Build Coastguard Worker     const std::string& initial_sample_name) const {
456*eb293b8fSAndroid Build Coastguard Worker   // Only return the first entry in the sample map if this is the single unwind use case.
457*eb293b8fSAndroid Build Coastguard Worker   // Otherwise return the inputted sample name so we can check if that is a valid sample name.
458*eb293b8fSAndroid Build Coastguard Worker   if (initial_sample_name == kSingleSample && samples_.size() == 1) {
459*eb293b8fSAndroid Build Coastguard Worker     return samples_.begin()->first;
460*eb293b8fSAndroid Build Coastguard Worker   }
461*eb293b8fSAndroid Build Coastguard Worker   return initial_sample_name;
462*eb293b8fSAndroid Build Coastguard Worker }
463*eb293b8fSAndroid Build Coastguard Worker 
IsValidUnwindSample(const std::string & sample_name,std::string * error_msg) const464*eb293b8fSAndroid Build Coastguard Worker bool OfflineUnwindUtils::IsValidUnwindSample(const std::string& sample_name,
465*eb293b8fSAndroid Build Coastguard Worker                                              std::string* error_msg) const {
466*eb293b8fSAndroid Build Coastguard Worker   if (!samples_.contains(sample_name)) {
467*eb293b8fSAndroid Build Coastguard Worker     std::stringstream err_stream;
468*eb293b8fSAndroid Build Coastguard Worker     err_stream << "Invalid sample name (offline file directory) '" << sample_name << "'.";
469*eb293b8fSAndroid Build Coastguard Worker     if (sample_name == kSingleSample) {
470*eb293b8fSAndroid Build Coastguard Worker       err_stream << " An explicit sample name must be provided for the multiple unwind use case "
471*eb293b8fSAndroid Build Coastguard Worker                     "of OfflineUnwindUtils (i.e. should not use the default sample name).";
472*eb293b8fSAndroid Build Coastguard Worker     }
473*eb293b8fSAndroid Build Coastguard Worker     *error_msg = err_stream.str();
474*eb293b8fSAndroid Build Coastguard Worker     return false;
475*eb293b8fSAndroid Build Coastguard Worker   }
476*eb293b8fSAndroid Build Coastguard Worker   return true;
477*eb293b8fSAndroid Build Coastguard Worker }
478*eb293b8fSAndroid Build Coastguard Worker 
479*eb293b8fSAndroid Build Coastguard Worker std::unordered_map<std::string, uint32_t> OfflineUnwindUtils::arm_regs_ = {
480*eb293b8fSAndroid Build Coastguard Worker     {"r0", ARM_REG_R0},  {"r1", ARM_REG_R1}, {"r2", ARM_REG_R2},   {"r3", ARM_REG_R3},
481*eb293b8fSAndroid Build Coastguard Worker     {"r4", ARM_REG_R4},  {"r5", ARM_REG_R5}, {"r6", ARM_REG_R6},   {"r7", ARM_REG_R7},
482*eb293b8fSAndroid Build Coastguard Worker     {"r8", ARM_REG_R8},  {"r9", ARM_REG_R9}, {"r10", ARM_REG_R10}, {"r11", ARM_REG_R11},
483*eb293b8fSAndroid Build Coastguard Worker     {"ip", ARM_REG_R12}, {"sp", ARM_REG_SP}, {"lr", ARM_REG_LR},   {"pc", ARM_REG_PC},
484*eb293b8fSAndroid Build Coastguard Worker };
485*eb293b8fSAndroid Build Coastguard Worker 
486*eb293b8fSAndroid Build Coastguard Worker std::unordered_map<std::string, uint32_t> OfflineUnwindUtils::arm64_regs_ = {
487*eb293b8fSAndroid Build Coastguard Worker     {"x0", ARM64_REG_R0},      {"x1", ARM64_REG_R1},   {"x2", ARM64_REG_R2},
488*eb293b8fSAndroid Build Coastguard Worker     {"x3", ARM64_REG_R3},      {"x4", ARM64_REG_R4},   {"x5", ARM64_REG_R5},
489*eb293b8fSAndroid Build Coastguard Worker     {"x6", ARM64_REG_R6},      {"x7", ARM64_REG_R7},   {"x8", ARM64_REG_R8},
490*eb293b8fSAndroid Build Coastguard Worker     {"x9", ARM64_REG_R9},      {"x10", ARM64_REG_R10}, {"x11", ARM64_REG_R11},
491*eb293b8fSAndroid Build Coastguard Worker     {"x12", ARM64_REG_R12},    {"x13", ARM64_REG_R13}, {"x14", ARM64_REG_R14},
492*eb293b8fSAndroid Build Coastguard Worker     {"x15", ARM64_REG_R15},    {"x16", ARM64_REG_R16}, {"x17", ARM64_REG_R17},
493*eb293b8fSAndroid Build Coastguard Worker     {"x18", ARM64_REG_R18},    {"x19", ARM64_REG_R19}, {"x20", ARM64_REG_R20},
494*eb293b8fSAndroid Build Coastguard Worker     {"x21", ARM64_REG_R21},    {"x22", ARM64_REG_R22}, {"x23", ARM64_REG_R23},
495*eb293b8fSAndroid Build Coastguard Worker     {"x24", ARM64_REG_R24},    {"x25", ARM64_REG_R25}, {"x26", ARM64_REG_R26},
496*eb293b8fSAndroid Build Coastguard Worker     {"x27", ARM64_REG_R27},    {"x28", ARM64_REG_R28}, {"x29", ARM64_REG_R29},
497*eb293b8fSAndroid Build Coastguard Worker     {"sp", ARM64_REG_SP},      {"lr", ARM64_REG_LR},   {"pc", ARM64_REG_PC},
498*eb293b8fSAndroid Build Coastguard Worker     {"pst", ARM64_REG_PSTATE},
499*eb293b8fSAndroid Build Coastguard Worker };
500*eb293b8fSAndroid Build Coastguard Worker 
501*eb293b8fSAndroid Build Coastguard Worker std::unordered_map<std::string, uint32_t> OfflineUnwindUtils::riscv64_regs_ = {
502*eb293b8fSAndroid Build Coastguard Worker     {"pc", RISCV64_REG_PC},   {"ra", RISCV64_REG_RA}, {"sp", RISCV64_REG_SP},
503*eb293b8fSAndroid Build Coastguard Worker     {"gp", RISCV64_REG_GP},   {"tp", RISCV64_REG_TP}, {"a0", RISCV64_REG_A0},
504*eb293b8fSAndroid Build Coastguard Worker     {"a1", RISCV64_REG_A1},   {"a2", RISCV64_REG_A2}, {"a3", RISCV64_REG_A3},
505*eb293b8fSAndroid Build Coastguard Worker     {"a4", RISCV64_REG_A4},   {"a5", RISCV64_REG_A5}, {"a6", RISCV64_REG_A6},
506*eb293b8fSAndroid Build Coastguard Worker     {"a7", RISCV64_REG_A7},   {"s0", RISCV64_REG_S0}, {"s1", RISCV64_REG_S1},
507*eb293b8fSAndroid Build Coastguard Worker     {"s2", RISCV64_REG_S2},   {"s3", RISCV64_REG_S3}, {"s4", RISCV64_REG_S4},
508*eb293b8fSAndroid Build Coastguard Worker     {"s5", RISCV64_REG_S5},   {"s6", RISCV64_REG_S6}, {"s7", RISCV64_REG_S7},
509*eb293b8fSAndroid Build Coastguard Worker     {"s8", RISCV64_REG_S8},   {"s9", RISCV64_REG_S9}, {"s10", RISCV64_REG_S10},
510*eb293b8fSAndroid Build Coastguard Worker     {"s11", RISCV64_REG_S11}, {"t0", RISCV64_REG_T0}, {"t1", RISCV64_REG_T1},
511*eb293b8fSAndroid Build Coastguard Worker     {"t2", RISCV64_REG_T2},   {"t3", RISCV64_REG_T3}, {"t4", RISCV64_REG_T4},
512*eb293b8fSAndroid Build Coastguard Worker     {"t5", RISCV64_REG_T5},   {"t6", RISCV64_REG_T6}, {"vlenb", RISCV64_REG_VLENB},
513*eb293b8fSAndroid Build Coastguard Worker };
514*eb293b8fSAndroid Build Coastguard Worker 
515*eb293b8fSAndroid Build Coastguard Worker std::unordered_map<std::string, uint32_t> OfflineUnwindUtils::x86_regs_ = {
516*eb293b8fSAndroid Build Coastguard Worker     {"eax", X86_REG_EAX}, {"ebx", X86_REG_EBX}, {"ecx", X86_REG_ECX},
517*eb293b8fSAndroid Build Coastguard Worker     {"edx", X86_REG_EDX}, {"ebp", X86_REG_EBP}, {"edi", X86_REG_EDI},
518*eb293b8fSAndroid Build Coastguard Worker     {"esi", X86_REG_ESI}, {"esp", X86_REG_ESP}, {"eip", X86_REG_EIP},
519*eb293b8fSAndroid Build Coastguard Worker };
520*eb293b8fSAndroid Build Coastguard Worker 
521*eb293b8fSAndroid Build Coastguard Worker std::unordered_map<std::string, uint32_t> OfflineUnwindUtils::x86_64_regs_ = {
522*eb293b8fSAndroid Build Coastguard Worker     {"rax", X86_64_REG_RAX}, {"rbx", X86_64_REG_RBX}, {"rcx", X86_64_REG_RCX},
523*eb293b8fSAndroid Build Coastguard Worker     {"rdx", X86_64_REG_RDX}, {"r8", X86_64_REG_R8},   {"r9", X86_64_REG_R9},
524*eb293b8fSAndroid Build Coastguard Worker     {"r10", X86_64_REG_R10}, {"r11", X86_64_REG_R11}, {"r12", X86_64_REG_R12},
525*eb293b8fSAndroid Build Coastguard Worker     {"r13", X86_64_REG_R13}, {"r14", X86_64_REG_R14}, {"r15", X86_64_REG_R15},
526*eb293b8fSAndroid Build Coastguard Worker     {"rdi", X86_64_REG_RDI}, {"rsi", X86_64_REG_RSI}, {"rbp", X86_64_REG_RBP},
527*eb293b8fSAndroid Build Coastguard Worker     {"rsp", X86_64_REG_RSP}, {"rip", X86_64_REG_RIP},
528*eb293b8fSAndroid Build Coastguard Worker };
529*eb293b8fSAndroid Build Coastguard Worker 
530*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
531