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