src/profiling: move proc-fd based unwinding helpers into src/p/common/
These are the classes I'm intending to share (including UnwindingMetadata).
Will replicate DoUnwind for now though (as it's a bit more tightly bound to
heapprofd's types and requirements).
Bug: 144281346
Change-Id: I1686fefc52d32d1ebeb142bca8e598a4c8b330ca
diff --git a/Android.bp b/Android.bp
index dc0bc6c..1dbff86 100644
--- a/Android.bp
+++ b/Android.bp
@@ -110,6 +110,8 @@
":perfetto_src_base_unix_socket",
":perfetto_src_ipc_client",
":perfetto_src_ipc_common",
+ ":perfetto_src_profiling_common_unwind_support",
+ ":perfetto_src_profiling_common_utils",
":perfetto_src_profiling_memory_daemon",
":perfetto_src_profiling_memory_proc_utils",
":perfetto_src_profiling_memory_ring_buffer",
@@ -1341,6 +1343,8 @@
":perfetto_src_ipc_common",
":perfetto_src_ipc_host",
":perfetto_src_perfetto_cmd_perfetto_atoms",
+ ":perfetto_src_profiling_common_unwind_support",
+ ":perfetto_src_profiling_common_utils",
":perfetto_src_profiling_memory_client",
":perfetto_src_profiling_memory_daemon",
":perfetto_src_profiling_memory_end_to_end_tests",
@@ -5592,6 +5596,22 @@
],
}
+// GN: //src/profiling/common:unwind_support
+filegroup {
+ name: "perfetto_src_profiling_common_unwind_support",
+ srcs: [
+ "src/profiling/common/unwind_support.cc",
+ ],
+}
+
+// GN: //src/profiling/common:utils
+filegroup {
+ name: "perfetto_src_profiling_common_utils",
+ srcs: [
+ "src/profiling/common/utils.cc",
+ ],
+}
+
// GN: //src/profiling:deobfuscator
filegroup {
name: "perfetto_src_profiling_deobfuscator",
@@ -5619,7 +5639,6 @@
"src/profiling/memory/page_idle_checker.cc",
"src/profiling/memory/system_property.cc",
"src/profiling/memory/unwinding.cc",
- "src/profiling/memory/utils.cc",
],
}
@@ -6961,6 +6980,8 @@
":perfetto_src_perfetto_cmd_protos_gen",
":perfetto_src_perfetto_cmd_trigger_producer",
":perfetto_src_perfetto_cmd_unittests",
+ ":perfetto_src_profiling_common_unwind_support",
+ ":perfetto_src_profiling_common_utils",
":perfetto_src_profiling_deobfuscator",
":perfetto_src_profiling_memory_client",
":perfetto_src_profiling_memory_daemon",
diff --git a/src/profiling/common/BUILD.gn b/src/profiling/common/BUILD.gn
new file mode 100644
index 0000000..767f969
--- /dev/null
+++ b/src/profiling/common/BUILD.gn
@@ -0,0 +1,36 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("../../../gn/perfetto.gni")
+
+source_set("unwind_support") {
+ public_deps = [ "../../../gn:libunwindstack" ]
+ deps = [
+ ":utils",
+ "../../../gn:default_deps",
+ "../../../src/base",
+ ]
+ sources = [
+ "unwind_support.cc",
+ "unwind_support.h",
+ ]
+}
+
+source_set("utils") {
+ deps = [ "../../../gn:default_deps" ]
+ sources = [
+ "utils.cc",
+ "utils.h",
+ ]
+}
diff --git a/src/profiling/common/unwind_support.cc b/src/profiling/common/unwind_support.cc
new file mode 100644
index 0000000..1d0d9f9
--- /dev/null
+++ b/src/profiling/common/unwind_support.cc
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "src/profiling/common/unwind_support.h"
+
+#include <inttypes.h>
+
+#include <procinfo/process_map.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+
+#include "perfetto/ext/base/file_utils.h"
+#include "src/profiling/common/utils.h"
+
+namespace perfetto {
+namespace profiling {
+
+StackOverlayMemory::StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,
+ uint64_t sp,
+ uint8_t* stack,
+ size_t size)
+ : mem_(std::move(mem)), sp_(sp), stack_end_(sp + size), stack_(stack) {}
+
+size_t StackOverlayMemory::Read(uint64_t addr, void* dst, size_t size) {
+ if (addr >= sp_ && addr + size <= stack_end_ && addr + size > sp_) {
+ size_t offset = static_cast<size_t>(addr - sp_);
+ memcpy(dst, stack_ + offset, size);
+ return size;
+ }
+
+ return mem_->Read(addr, dst, size);
+}
+
+FDMemory::FDMemory(base::ScopedFile mem_fd) : mem_fd_(std::move(mem_fd)) {}
+
+size_t FDMemory::Read(uint64_t addr, void* dst, size_t size) {
+ ssize_t rd = ReadAtOffsetClobberSeekPos(*mem_fd_, dst, size,
+ static_cast<off64_t>(addr));
+ if (rd == -1) {
+ PERFETTO_DPLOG("read of %zu at offset %" PRIu64, size, addr);
+ return 0;
+ }
+ return static_cast<size_t>(rd);
+}
+
+FileDescriptorMaps::FileDescriptorMaps(base::ScopedFile fd)
+ : fd_(std::move(fd)) {}
+
+bool FileDescriptorMaps::Parse() {
+ // If the process has already exited, lseek or ReadFileDescriptor will
+ // return false.
+ if (lseek(*fd_, 0, SEEK_SET) == -1)
+ return false;
+
+ std::string content;
+ if (!base::ReadFileDescriptor(*fd_, &content))
+ return false;
+
+ unwindstack::MapInfo* prev_map = nullptr;
+ unwindstack::MapInfo* prev_real_map = nullptr;
+ return android::procinfo::ReadMapFileContent(
+ &content[0], [&](uint64_t start, uint64_t end, uint16_t flags,
+ uint64_t pgoff, ino_t, const char* name) {
+ // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
+ if (strncmp(name, "/dev/", 5) == 0 &&
+ strncmp(name + 5, "ashmem/", 7) != 0) {
+ flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
+ }
+ maps_.emplace_back(new unwindstack::MapInfo(
+ prev_map, prev_real_map, start, end, pgoff, flags, name));
+ prev_map = maps_.back().get();
+ if (!prev_map->IsBlank()) {
+ prev_real_map = prev_map;
+ }
+ });
+}
+
+void FileDescriptorMaps::Reset() {
+ maps_.clear();
+}
+
+} // namespace profiling
+} // namespace perfetto
diff --git a/src/profiling/common/unwind_support.h b/src/profiling/common/unwind_support.h
new file mode 100644
index 0000000..f840273
--- /dev/null
+++ b/src/profiling/common/unwind_support.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_PROFILING_COMMON_UNWIND_SUPPORT_H_
+#define SRC_PROFILING_COMMON_UNWIND_SUPPORT_H_
+
+// defines PERFETTO_BUILDFLAG
+#include "perfetto/base/build_config.h"
+
+#include <unwindstack/Maps.h>
+#include <unwindstack/Unwinder.h>
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+#include <unwindstack/DexFiles.h>
+#include <unwindstack/JitDebug.h>
+#endif
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/time.h"
+#include "perfetto/ext/base/scoped_file.h"
+
+namespace perfetto {
+namespace profiling {
+
+// Read /proc/[pid]/maps from an open file descriptor.
+// TODO(fmayer): Figure out deduplication to other maps.
+class FileDescriptorMaps : public unwindstack::Maps {
+ public:
+ FileDescriptorMaps(base::ScopedFile fd);
+
+ FileDescriptorMaps(const FileDescriptorMaps&) = delete;
+ FileDescriptorMaps& operator=(const FileDescriptorMaps&) = delete;
+
+ FileDescriptorMaps(FileDescriptorMaps&& m) : Maps(std::move(m)) {
+ fd_ = std::move(m.fd_);
+ }
+
+ FileDescriptorMaps& operator=(FileDescriptorMaps&& m) {
+ if (&m != this)
+ fd_ = std::move(m.fd_);
+ Maps::operator=(std::move(m));
+ return *this;
+ }
+
+ virtual ~FileDescriptorMaps() override = default;
+
+ bool Parse() override;
+ void Reset();
+
+ private:
+ base::ScopedFile fd_;
+};
+
+class FDMemory : public unwindstack::Memory {
+ public:
+ FDMemory(base::ScopedFile mem_fd);
+ size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+ private:
+ base::ScopedFile mem_fd_;
+};
+
+// Overlays size bytes pointed to by stack for addresses in [sp, sp + size).
+// Addresses outside of that range are read from mem_fd, which should be an fd
+// that opened /proc/[pid]/mem.
+class StackOverlayMemory : public unwindstack::Memory {
+ public:
+ StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,
+ uint64_t sp,
+ uint8_t* stack,
+ size_t size);
+ size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+ private:
+ std::shared_ptr<unwindstack::Memory> mem_;
+ uint64_t sp_;
+ uint64_t stack_end_;
+ uint8_t* stack_;
+};
+
+struct UnwindingMetadata {
+ UnwindingMetadata(pid_t p, base::ScopedFile maps_fd, base::ScopedFile mem)
+ : pid(p),
+ maps(std::move(maps_fd)),
+ fd_mem(std::make_shared<FDMemory>(std::move(mem)))
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+ ,
+ jit_debug(std::unique_ptr<unwindstack::JitDebug>(
+ new unwindstack::JitDebug(fd_mem))),
+ dex_files(std::unique_ptr<unwindstack::DexFiles>(
+ new unwindstack::DexFiles(fd_mem)))
+#endif
+ {
+ bool parsed = maps.Parse();
+ PERFETTO_DCHECK(parsed);
+ }
+ void ReparseMaps() {
+ reparses++;
+ maps.Reset();
+ maps.Parse();
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+ jit_debug = std::unique_ptr<unwindstack::JitDebug>(
+ new unwindstack::JitDebug(fd_mem));
+ dex_files = std::unique_ptr<unwindstack::DexFiles>(
+ new unwindstack::DexFiles(fd_mem));
+#endif
+ }
+ pid_t pid;
+ FileDescriptorMaps maps;
+ // The API of libunwindstack expects shared_ptr for Memory.
+ std::shared_ptr<unwindstack::Memory> fd_mem;
+ uint64_t reparses = 0;
+ base::TimeMillis last_maps_reparse_time{0};
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+ std::unique_ptr<unwindstack::JitDebug> jit_debug;
+ std::unique_ptr<unwindstack::DexFiles> dex_files;
+#endif
+};
+
+} // namespace profiling
+} // namespace perfetto
+
+#endif // SRC_PROFILING_COMMON_UNWIND_SUPPORT_H_
diff --git a/src/profiling/memory/utils.cc b/src/profiling/common/utils.cc
similarity index 97%
rename from src/profiling/memory/utils.cc
rename to src/profiling/common/utils.cc
index b424192..019eb1b 100644
--- a/src/profiling/memory/utils.cc
+++ b/src/profiling/common/utils.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "src/profiling/memory/utils.h"
+#include "src/profiling/common/utils.h"
namespace perfetto {
namespace profiling {
diff --git a/src/profiling/memory/utils.h b/src/profiling/common/utils.h
similarity index 88%
rename from src/profiling/memory/utils.h
rename to src/profiling/common/utils.h
index 5e375c9..01fbf99 100644
--- a/src/profiling/memory/utils.h
+++ b/src/profiling/common/utils.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_PROFILING_MEMORY_UTILS_H_
-#define SRC_PROFILING_MEMORY_UTILS_H_
+#ifndef SRC_PROFILING_COMMON_UTILS_H_
+#define SRC_PROFILING_COMMON_UTILS_H_
#include <unistd.h>
@@ -31,7 +31,7 @@
void* buf,
size_t count,
off64_t addr);
-}
+} // namespace profiling
} // namespace perfetto
-#endif // SRC_PROFILING_MEMORY_UTILS_H_
+#endif // SRC_PROFILING_COMMON_UTILS_H_
diff --git a/src/profiling/memory/BUILD.gn b/src/profiling/memory/BUILD.gn
index 6c4ef75..76b9dc7 100644
--- a/src/profiling/memory/BUILD.gn
+++ b/src/profiling/memory/BUILD.gn
@@ -140,6 +140,8 @@
"../../base:unix_socket",
"../../tracing/core",
"../../tracing/ipc/producer",
+ "../common:unwind_support",
+ "../common:utils",
]
public_deps = [
"../../../gn:libunwindstack",
@@ -165,8 +167,6 @@
"unwinding.cc",
"unwinding.h",
"unwound_messages.h",
- "utils.cc",
- "utils.h",
]
}
@@ -202,6 +202,8 @@
"../../base",
"../../base:test_support",
"../../tracing/core",
+ "../common:unwind_support",
+ "../common:utils",
]
sources = [
"bookkeeping_unittest.cc",
@@ -248,6 +250,8 @@
"../../../gn:default_deps",
"../../base",
"../../tracing/core",
+ "../common:unwind_support",
+ "../common:utils",
]
}
diff --git a/src/profiling/memory/page_idle_checker.cc b/src/profiling/memory/page_idle_checker.cc
index 7e639b5..56eec2d 100644
--- a/src/profiling/memory/page_idle_checker.cc
+++ b/src/profiling/memory/page_idle_checker.cc
@@ -16,7 +16,7 @@
#include "src/profiling/memory/page_idle_checker.h"
#include "perfetto/ext/base/utils.h"
-#include "src/profiling/memory/utils.h"
+#include "src/profiling/common/utils.h"
#include <inttypes.h>
#include <vector>
diff --git a/src/profiling/memory/unwinding.cc b/src/profiling/memory/unwinding.cc
index 339077b..587bea4 100644
--- a/src/profiling/memory/unwinding.cc
+++ b/src/profiling/memory/unwinding.cc
@@ -51,7 +51,7 @@
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/base/thread_task_runner.h"
-#include "src/profiling/memory/utils.h"
+#include "src/profiling/common/utils.h"
#include "src/profiling/memory/wire_protocol.h"
namespace perfetto {
@@ -117,70 +117,6 @@
return ret;
}
-StackOverlayMemory::StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,
- uint64_t sp,
- uint8_t* stack,
- size_t size)
- : mem_(std::move(mem)), sp_(sp), stack_end_(sp + size), stack_(stack) {}
-
-size_t StackOverlayMemory::Read(uint64_t addr, void* dst, size_t size) {
- if (addr >= sp_ && addr + size <= stack_end_ && addr + size > sp_) {
- size_t offset = static_cast<size_t>(addr - sp_);
- memcpy(dst, stack_ + offset, size);
- return size;
- }
-
- return mem_->Read(addr, dst, size);
-}
-
-FDMemory::FDMemory(base::ScopedFile mem_fd) : mem_fd_(std::move(mem_fd)) {}
-
-size_t FDMemory::Read(uint64_t addr, void* dst, size_t size) {
- ssize_t rd = ReadAtOffsetClobberSeekPos(*mem_fd_, dst, size,
- static_cast<off64_t>(addr));
- if (rd == -1) {
- PERFETTO_DPLOG("read of %zu at offset %" PRIu64, size, addr);
- return 0;
- }
- return static_cast<size_t>(rd);
-}
-
-FileDescriptorMaps::FileDescriptorMaps(base::ScopedFile fd)
- : fd_(std::move(fd)) {}
-
-bool FileDescriptorMaps::Parse() {
- // If the process has already exited, lseek or ReadFileDescriptor will
- // return false.
- if (lseek(*fd_, 0, SEEK_SET) == -1)
- return false;
-
- std::string content;
- if (!base::ReadFileDescriptor(*fd_, &content))
- return false;
-
- unwindstack::MapInfo* prev_map = nullptr;
- unwindstack::MapInfo* prev_real_map = nullptr;
- return android::procinfo::ReadMapFileContent(
- &content[0], [&](uint64_t start, uint64_t end, uint16_t flags,
- uint64_t pgoff, ino_t, const char* name) {
- // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
- if (strncmp(name, "/dev/", 5) == 0 &&
- strncmp(name + 5, "ashmem/", 7) != 0) {
- flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
- }
- maps_.emplace_back(
- new unwindstack::MapInfo(prev_map, prev_real_map, start, end, pgoff, flags, name));
- prev_map = maps_.back().get();
- if (!prev_map->IsBlank()) {
- prev_real_map = prev_map;
- }
- });
-}
-
-void FileDescriptorMaps::Reset() {
- maps_.clear();
-}
-
bool DoUnwind(WireMessage* msg, UnwindingMetadata* metadata, AllocRecord* out) {
AllocMetadata* alloc_metadata = msg->alloc_header;
std::unique_ptr<unwindstack::Regs> regs(CreateRegsFromRawData(
diff --git a/src/profiling/memory/unwinding.h b/src/profiling/memory/unwinding.h
index a702c64..b1692a6 100644
--- a/src/profiling/memory/unwinding.h
+++ b/src/profiling/memory/unwinding.h
@@ -17,20 +17,13 @@
#ifndef SRC_PROFILING_MEMORY_UNWINDING_H_
#define SRC_PROFILING_MEMORY_UNWINDING_H_
-#include "perfetto/base/build_config.h"
-
-#include <unwindstack/Maps.h>
-#include <unwindstack/Unwinder.h>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-#include <unwindstack/DexFiles.h>
-#include <unwindstack/JitDebug.h>
-#endif
+#include <unwindstack/Regs.h>
#include "perfetto/base/time.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/thread_task_runner.h"
#include "perfetto/ext/tracing/core/basic_types.h"
+#include "src/profiling/common/unwind_support.h"
#include "src/profiling/memory/bookkeeping.h"
#include "src/profiling/memory/unwound_messages.h"
#include "src/profiling/memory/wire_protocol.h"
@@ -42,101 +35,6 @@
unwindstack::ArchEnum arch,
void* raw_data);
-// Read /proc/[pid]/maps from an open file descriptor.
-// TODO(fmayer): Figure out deduplication to other maps.
-class FileDescriptorMaps : public unwindstack::Maps {
- public:
- FileDescriptorMaps(base::ScopedFile fd);
-
- FileDescriptorMaps(const FileDescriptorMaps&) = delete;
- FileDescriptorMaps& operator=(const FileDescriptorMaps&) = delete;
-
- FileDescriptorMaps(FileDescriptorMaps&& m) : Maps(std::move(m)) {
- fd_ = std::move(m.fd_);
- }
-
- FileDescriptorMaps& operator=(FileDescriptorMaps&& m) {
- if (&m != this)
- fd_ = std::move(m.fd_);
- Maps::operator=(std::move(m));
- return *this;
- }
-
- virtual ~FileDescriptorMaps() override = default;
-
- bool Parse() override;
- void Reset();
-
- private:
- base::ScopedFile fd_;
-};
-
-class FDMemory : public unwindstack::Memory {
- public:
- FDMemory(base::ScopedFile mem_fd);
- size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
- base::ScopedFile mem_fd_;
-};
-
-// Overlays size bytes pointed to by stack for addresses in [sp, sp + size).
-// Addresses outside of that range are read from mem_fd, which should be an fd
-// that opened /proc/[pid]/mem.
-class StackOverlayMemory : public unwindstack::Memory {
- public:
- StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,
- uint64_t sp,
- uint8_t* stack,
- size_t size);
- size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
- std::shared_ptr<unwindstack::Memory> mem_;
- uint64_t sp_;
- uint64_t stack_end_;
- uint8_t* stack_;
-};
-
-struct UnwindingMetadata {
- UnwindingMetadata(pid_t p, base::ScopedFile maps_fd, base::ScopedFile mem)
- : pid(p),
- maps(std::move(maps_fd)),
- fd_mem(std::make_shared<FDMemory>(std::move(mem)))
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
- ,
- jit_debug(std::unique_ptr<unwindstack::JitDebug>(
- new unwindstack::JitDebug(fd_mem))),
- dex_files(std::unique_ptr<unwindstack::DexFiles>(
- new unwindstack::DexFiles(fd_mem)))
-#endif
- {
- bool parsed = maps.Parse();
- PERFETTO_DCHECK(parsed);
- }
- void ReparseMaps() {
- reparses++;
- maps.Reset();
- maps.Parse();
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
- jit_debug = std::unique_ptr<unwindstack::JitDebug>(
- new unwindstack::JitDebug(fd_mem));
- dex_files = std::unique_ptr<unwindstack::DexFiles>(
- new unwindstack::DexFiles(fd_mem));
-#endif
- }
- pid_t pid;
- FileDescriptorMaps maps;
- // The API of libunwindstack expects shared_ptr for Memory.
- std::shared_ptr<unwindstack::Memory> fd_mem;
- uint64_t reparses = 0;
- base::TimeMillis last_maps_reparse_time{0};
-#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
- std::unique_ptr<unwindstack::JitDebug> jit_debug;
- std::unique_ptr<unwindstack::DexFiles> dex_files;
-#endif
-};
-
bool DoUnwind(WireMessage*, UnwindingMetadata* metadata, AllocRecord* out);
class UnwindingWorker : public base::UnixSocket::EventListener {
diff --git a/src/profiling/memory/unwinding_fuzzer.cc b/src/profiling/memory/unwinding_fuzzer.cc
index c2046b0..29991ba 100644
--- a/src/profiling/memory/unwinding_fuzzer.cc
+++ b/src/profiling/memory/unwinding_fuzzer.cc
@@ -19,6 +19,7 @@
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/tracing/core/basic_types.h"
+#include "src/profiling/common/unwind_support.h"
#include "src/profiling/memory/shared_ring_buffer.h"
#include "src/profiling/memory/unwinding.h"
#include "src/profiling/memory/unwound_messages.h"
diff --git a/src/profiling/memory/unwinding_unittest.cc b/src/profiling/memory/unwinding_unittest.cc
index b52a7ce..893bf8e 100644
--- a/src/profiling/memory/unwinding_unittest.cc
+++ b/src/profiling/memory/unwinding_unittest.cc
@@ -23,6 +23,7 @@
#include <unwindstack/RegsGetLocal.h>
#include "perfetto/ext/base/scoped_file.h"
+#include "src/profiling/common/unwind_support.h"
#include "src/profiling/memory/client.h"
#include "src/profiling/memory/wire_protocol.h"
#include "test/gtest_and_gmock.h"