Authors: @safayat-google
Status: Draft
Currently, unwinding in Perfetto is based on the android-unwinding/libunwindstack library. This is a dependency that we want to remove for several reasons:
libunwindstack API break our builds.libunwindstack's implementation does not benefit us.Pending
libunwindstack.perfetto::profiling namespace for the new types/classes.perfetto::profiling::unwinding namespace to avoid build breaks.heapprofd and traced_perf usage patterns.repo-root/ └── src/ └── profiling/ └── common/ └── unwinding/ ├── Regs.h ├── Memory.h ├── Maps.h ├── Elf.h └── Unwinder.h
1.1 Implement Regs.h API 1.2 Implement Memory & Maps API 1.3 Implement Elf.h API 1.4 Implement the Unwinder API
2.1 Migrate heapprofd unwinding usage 2.2 Migrate traced_perf unwinding usage
3.1 Memory usage optimization
- Remove any ELF-related memory overhead that we do not need.
3.2 Other feature or CPU/memory optimizations
unwindstack/Unwinder.hstruct FrameData { num, rel_pc, pc, sp, function_name, offset, map_info } ... class Unwinder { Unwinder(size_t max_frames, Maps* maps, Regs* regs, std::shared_ptr<Memory> process_memory); ... virtual void Unwind(initial_map_names_to_skip, map_suffixes_to_ignore); ... void SetJitDebug(JitDebug* jit_debug); void SetDexFiles(DexFiles* dex_files); ... }
unwindstack/Memory.h// abstraction to read a block of memory from file/cache etc class Memory { ... virtual size_t Read(addr, dst, size); // local unwinding CreateProcessMemoryCached(pid); // remote unwinding CreateProcessMemoryThreadCached(pid); }
unwindstack/Maps.h// Read /proc/[pid]/maps from an open file descriptor unwindstack::Maps { std::vector<std::shared_ptr<MapInfo>> maps_; }
unwindstack/Regs.h// Core API to capture register snapshots inline AsmGetRegs(void* regs); // Different register mappings on different architectures enum X86Reg : uint16_t { X86_REG_EAX = 0, ... } enum X86_64Reg, ArmReg, Arm64Reg
unwindstack/Elf.hclass Elf { public: Elf(std::shared_ptr<Memory>& memory); // we call it to reset the elf cache static void SetCachingEnabled(bool enable); }
unwindstack/JitDebug.h and unwindstack/DexFiles.hCreateJitDebug(arch, memory, search_libs = {}); CreateDexFiles(arch, memory, search_libs = {});
libunwindstack that internally depends on libunwindstack.libunwindstack directly.Pro:
libunwindstack's active development.libunwindstack, we only need to update our abstraction layer.Con:
libunwindstack.libunwindstack.Pro:
Con: