1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/profiling/common/unwind_support.h"
18
19 #include <cinttypes>
20
21 #include <procinfo/process_map.h>
22 #include <unwindstack/Maps.h>
23 #include <unwindstack/Memory.h>
24
25 #include "perfetto/ext/base/file_utils.h"
26
27 namespace perfetto {
28 namespace profiling {
29
StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,uint64_t sp,const uint8_t * stack,size_t size)30 StackOverlayMemory::StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,
31 uint64_t sp,
32 const uint8_t* stack,
33 size_t size)
34 : mem_(std::move(mem)), sp_(sp), stack_end_(sp + size), stack_(stack) {}
35
Read(uint64_t addr,void * dst,size_t size)36 size_t StackOverlayMemory::Read(uint64_t addr, void* dst, size_t size) {
37 if (addr >= sp_ && addr + size <= stack_end_ && addr + size > sp_) {
38 size_t offset = static_cast<size_t>(addr - sp_);
39 memcpy(dst, stack_ + offset, size);
40 return size;
41 }
42
43 return mem_->Read(addr, dst, size);
44 }
45
FDMemory(base::ScopedFile mem_fd)46 FDMemory::FDMemory(base::ScopedFile mem_fd) : mem_fd_(std::move(mem_fd)) {}
47
Read(uint64_t addr,void * dst,size_t size)48 size_t FDMemory::Read(uint64_t addr, void* dst, size_t size) {
49 ssize_t rd = pread64(*mem_fd_, dst, size, static_cast<off64_t>(addr));
50 if (PERFETTO_UNLIKELY(rd == -1)) {
51 PERFETTO_PLOG("Failed remote pread of %zu bytes at address %" PRIx64, size,
52 addr);
53 return 0;
54 }
55 return static_cast<size_t>(rd);
56 }
57
FDMaps(base::ScopedFile fd)58 FDMaps::FDMaps(base::ScopedFile fd) : fd_(std::move(fd)) {}
59
Parse()60 bool FDMaps::Parse() {
61 // If the process has already exited, lseek or ReadFileDescriptor will
62 // return false.
63 if (lseek(*fd_, 0, SEEK_SET) == -1)
64 return false;
65
66 std::string content;
67 if (!base::ReadFileDescriptor(*fd_, &content))
68 return false;
69
70 unwindstack::SharedString name("");
71 std::shared_ptr<unwindstack::MapInfo> prev_map;
72 return android::procinfo::ReadMapFileContent(
73 &content[0], [&](const android::procinfo::MapInfo& mapinfo) {
74 // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
75 auto flags = mapinfo.flags;
76 if (strncmp(mapinfo.name.c_str(), "/dev/", 5) == 0 &&
77 strncmp(mapinfo.name.c_str() + 5, "ashmem/", 7) != 0) {
78 flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
79 }
80 // Share the string if it matches for consecutive maps.
81 if (name != mapinfo.name) {
82 name = unwindstack::SharedString(mapinfo.name);
83 }
84 maps_.emplace_back(unwindstack::MapInfo::Create(
85 prev_map, mapinfo.start, mapinfo.end, mapinfo.pgoff,
86 flags, name));
87 prev_map = maps_.back();
88 });
89 }
90
Reset()91 void FDMaps::Reset() {
92 maps_.clear();
93 }
94
UnwindingMetadata(base::ScopedFile maps_fd,base::ScopedFile mem_fd)95 UnwindingMetadata::UnwindingMetadata(base::ScopedFile maps_fd,
96 base::ScopedFile mem_fd)
97 : fd_maps(std::move(maps_fd)),
98 fd_mem(std::make_shared<FDMemory>(std::move(mem_fd))) {
99 if (!fd_maps.Parse())
100 PERFETTO_DLOG("Failed initial maps parse");
101 }
102
ReparseMaps()103 void UnwindingMetadata::ReparseMaps() {
104 reparses++;
105 fd_maps.Reset();
106 fd_maps.Parse();
107 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
108 jit_debug.reset();
109 dex_files.reset();
110 #endif
111 }
112
113 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
GetJitDebug(unwindstack::ArchEnum arch)114 unwindstack::JitDebug* UnwindingMetadata::GetJitDebug(unwindstack::ArchEnum arch) {
115 if (jit_debug.get() == nullptr) {
116 std::vector<std::string> search_libs{"libart.so", "libartd.so"};
117 jit_debug = unwindstack::CreateJitDebug(arch, fd_mem, search_libs);
118 }
119 return jit_debug.get();
120 }
121
GetDexFiles(unwindstack::ArchEnum arch)122 unwindstack::DexFiles* UnwindingMetadata::GetDexFiles(unwindstack::ArchEnum arch) {
123 if (dex_files.get() == nullptr) {
124 std::vector<std::string> search_libs{"libart.so", "libartd.so"};
125 dex_files = unwindstack::CreateDexFiles(arch, fd_mem, search_libs);
126 }
127 return dex_files.get();
128 }
129 #endif
130
GetBuildId(const unwindstack::FrameData & frame)131 const std::string& UnwindingMetadata::GetBuildId(
132 const unwindstack::FrameData& frame) {
133 if (frame.map_info != nullptr && !frame.map_info->name().empty()) {
134 return frame.map_info->GetBuildID();
135 }
136
137 return empty_string_;
138 }
139
StringifyLibUnwindstackError(unwindstack::ErrorCode e)140 std::string StringifyLibUnwindstackError(unwindstack::ErrorCode e) {
141 switch (e) {
142 case unwindstack::ERROR_NONE:
143 return "NONE";
144 case unwindstack::ERROR_MEMORY_INVALID:
145 return "MEMORY_INVALID";
146 case unwindstack::ERROR_UNWIND_INFO:
147 return "UNWIND_INFO";
148 case unwindstack::ERROR_UNSUPPORTED:
149 return "UNSUPPORTED";
150 case unwindstack::ERROR_INVALID_MAP:
151 return "INVALID_MAP";
152 case unwindstack::ERROR_MAX_FRAMES_EXCEEDED:
153 return "MAX_FRAME_EXCEEDED";
154 case unwindstack::ERROR_REPEATED_FRAME:
155 return "REPEATED_FRAME";
156 case unwindstack::ERROR_INVALID_ELF:
157 return "INVALID_ELF";
158 case unwindstack::ERROR_SYSTEM_CALL:
159 return "SYSTEM_CALL";
160 case unwindstack::ERROR_THREAD_DOES_NOT_EXIST:
161 return "THREAD_DOES_NOT_EXIST";
162 case unwindstack::ERROR_THREAD_TIMEOUT:
163 return "THREAD_TIMEOUT";
164 case unwindstack::ERROR_BAD_ARCH:
165 return "BAD_ARCH";
166 case unwindstack::ERROR_MAPS_PARSE:
167 return "MAPS_PARSE";
168 case unwindstack::ERROR_INVALID_PARAMETER:
169 return "INVALID_PARAMETER";
170 }
171 }
172
173 } // namespace profiling
174 } // namespace perfetto
175