// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_PROFILER_ARM_CFI_TABLE_H_ #define BASE_PROFILER_ARM_CFI_TABLE_H_ #include #include "base/base_export.h" #include "base/containers/buffer_iterator.h" #include "base/containers/span.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace base { // This class implements methods to read and parse the arm Call Frame // Information (CFI) for Chrome, which contains tables for unwinding Chrome // functions. For detailed description of the format, see // extract_unwind_tables.py. class BASE_EXPORT ArmCFITable { public: // The CFI information that correspond to an instruction. {0, 0} is a valid // entry and should be interpreted as the default rule: // .cfa: sp; .cfa = lr (link register). struct FrameEntry { // The offset of the call frame address (CFA) of previous function, relative // to the current stack pointer. Rule for unwinding CFA: // .cfa: sp + cfa_offset. uint16_t cfa_offset = 0; // The offset of location of return address (RA), relative to the previous // call frame address. Rule for unwinding RA: // .ra = *(cfa - ra_offset). uint16_t ra_offset = 0; }; // Parses |cfi_data| and creates a ArmCFITable that reads from it. // |cfi_data| is required to remain valid for the lifetime of the object. static std::unique_ptr Parse(span cfi_data); ArmCFITable(span function_addresses, span entry_data_indices, span entry_data); ArmCFITable(const ArmCFITable&) = delete; ArmCFITable& operator=(const ArmCFITable&) = delete; ~ArmCFITable(); // Finds the CFI row for the given |address| in terms of offset from the // start of the current binary. Concurrent calls are thread safe. absl::optional FindEntryForAddress(uintptr_t address) const; size_t GetTableSizeForTesting() const { return function_addresses_.size(); } private: // The UNW_INDEX table allows readers to map functions start addresses to // that function's respective entry in the UNW_DATA table. // - A function's start address is at 0x123, and // - function_addresses_[2] == 0x123, and // - entry_data_indices_[2] = 42, then // - entry_data_[42] is the corresponding entry in the UNW_DATA table for // the function with the start address of 0x123 // // Note that function_addresses is sorted to facilitate easy lookup. const span function_addresses_; const span entry_data_indices_; // A reference to the UNW_DATA table. Each entry in the UNW_DATA table // corresponds to a function, which in turn corresponds to an array of // CFIDataRows. (see arm_cfi_reader.cc). const span entry_data_; }; } // namespace base #endif // BASE_PROFILER_ARM_CFI_TABLE_H_