blob: 061ed61e35e0a04324d867cb95630523fcac8a48 [file] [log] [blame]
Ryan Savitski33fd8b72020-02-04 15:06:15 +00001/*
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#ifndef SRC_PROFILING_COMMON_UNWIND_SUPPORT_H_
18#define SRC_PROFILING_COMMON_UNWIND_SUPPORT_H_
19
20// defines PERFETTO_BUILDFLAG
21#include "perfetto/base/build_config.h"
22
Ryan Savitskifdeb11f2020-02-05 16:53:45 +000023#include <memory>
24#include <string>
25
Ryan Savitski33fd8b72020-02-04 15:06:15 +000026#include <unwindstack/Maps.h>
27#include <unwindstack/Unwinder.h>
28#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
29#include <unwindstack/DexFiles.h>
30#include <unwindstack/JitDebug.h>
31#endif
32
33#include "perfetto/base/logging.h"
34#include "perfetto/base/time.h"
35#include "perfetto/ext/base/scoped_file.h"
36
37namespace perfetto {
38namespace profiling {
39
Ryan Savitskifdeb11f2020-02-05 16:53:45 +000040// libunwindstack's FrameData annotated with the build_id.
41struct FrameData {
42 FrameData(unwindstack::FrameData f, std::string id)
43 : frame(std::move(f)), build_id(std::move(id)) {}
44
45 unwindstack::FrameData frame;
46 std::string build_id;
47};
48
Ryan Savitski33fd8b72020-02-04 15:06:15 +000049// Read /proc/[pid]/maps from an open file descriptor.
50// TODO(fmayer): Figure out deduplication to other maps.
Ryan Savitski3686d292020-02-04 16:44:56 +000051class FDMaps : public unwindstack::Maps {
Ryan Savitski33fd8b72020-02-04 15:06:15 +000052 public:
Ryan Savitski3686d292020-02-04 16:44:56 +000053 FDMaps(base::ScopedFile fd);
Ryan Savitski33fd8b72020-02-04 15:06:15 +000054
Ryan Savitski3686d292020-02-04 16:44:56 +000055 FDMaps(const FDMaps&) = delete;
56 FDMaps& operator=(const FDMaps&) = delete;
Ryan Savitski33fd8b72020-02-04 15:06:15 +000057
Ryan Savitski3686d292020-02-04 16:44:56 +000058 FDMaps(FDMaps&& m) : Maps(std::move(m)) { fd_ = std::move(m.fd_); }
Ryan Savitski33fd8b72020-02-04 15:06:15 +000059
Ryan Savitski3686d292020-02-04 16:44:56 +000060 FDMaps& operator=(FDMaps&& m) {
Ryan Savitski33fd8b72020-02-04 15:06:15 +000061 if (&m != this)
62 fd_ = std::move(m.fd_);
63 Maps::operator=(std::move(m));
64 return *this;
65 }
66
Ryan Savitski3686d292020-02-04 16:44:56 +000067 virtual ~FDMaps() override = default;
Ryan Savitski33fd8b72020-02-04 15:06:15 +000068
69 bool Parse() override;
70 void Reset();
71
72 private:
73 base::ScopedFile fd_;
74};
75
76class FDMemory : public unwindstack::Memory {
77 public:
78 FDMemory(base::ScopedFile mem_fd);
79 size_t Read(uint64_t addr, void* dst, size_t size) override;
80
81 private:
82 base::ScopedFile mem_fd_;
83};
84
85// Overlays size bytes pointed to by stack for addresses in [sp, sp + size).
86// Addresses outside of that range are read from mem_fd, which should be an fd
87// that opened /proc/[pid]/mem.
88class StackOverlayMemory : public unwindstack::Memory {
89 public:
90 StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,
91 uint64_t sp,
92 uint8_t* stack,
93 size_t size);
94 size_t Read(uint64_t addr, void* dst, size_t size) override;
95
96 private:
97 std::shared_ptr<unwindstack::Memory> mem_;
98 uint64_t sp_;
99 uint64_t stack_end_;
100 uint8_t* stack_;
101};
102
103struct UnwindingMetadata {
Ryan Savitskifdeb11f2020-02-05 16:53:45 +0000104 UnwindingMetadata(base::ScopedFile maps_fd, base::ScopedFile mem_fd);
105
106 // move-only
107 UnwindingMetadata(const UnwindingMetadata&) = delete;
108 UnwindingMetadata& operator=(const UnwindingMetadata&) = delete;
109
110 UnwindingMetadata(UnwindingMetadata&&) = default;
111 UnwindingMetadata& operator=(UnwindingMetadata&&) = default;
112
113 void ReparseMaps();
114
115 FrameData AnnotateFrame(unwindstack::FrameData frame);
116
Ryan Savitski3686d292020-02-04 16:44:56 +0000117 FDMaps fd_maps;
Ryan Savitski33fd8b72020-02-04 15:06:15 +0000118 // The API of libunwindstack expects shared_ptr for Memory.
119 std::shared_ptr<unwindstack::Memory> fd_mem;
120 uint64_t reparses = 0;
121 base::TimeMillis last_maps_reparse_time{0};
122#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
123 std::unique_ptr<unwindstack::JitDebug> jit_debug;
124 std::unique_ptr<unwindstack::DexFiles> dex_files;
125#endif
126};
127
128} // namespace profiling
129} // namespace perfetto
130
131#endif // SRC_PROFILING_COMMON_UNWIND_SUPPORT_H_