arm_cfi_table.h 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_PROFILER_ARM_CFI_TABLE_H_
  5. #define BASE_PROFILER_ARM_CFI_TABLE_H_
  6. #include <memory>
  7. #include "base/base_export.h"
  8. #include "base/containers/buffer_iterator.h"
  9. #include "base/containers/span.h"
  10. #include "third_party/abseil-cpp/absl/types/optional.h"
  11. namespace base {
  12. // This class implements methods to read and parse the arm Call Frame
  13. // Information (CFI) for Chrome, which contains tables for unwinding Chrome
  14. // functions. For detailed description of the format, see
  15. // extract_unwind_tables.py.
  16. class BASE_EXPORT ArmCFITable {
  17. public:
  18. // The CFI information that correspond to an instruction. {0, 0} is a valid
  19. // entry and should be interpreted as the default rule:
  20. // .cfa: sp; .cfa = lr (link register).
  21. struct FrameEntry {
  22. // The offset of the call frame address (CFA) of previous function, relative
  23. // to the current stack pointer. Rule for unwinding CFA:
  24. // .cfa: sp + cfa_offset.
  25. uint16_t cfa_offset = 0;
  26. // The offset of location of return address (RA), relative to the previous
  27. // call frame address. Rule for unwinding RA:
  28. // .ra = *(cfa - ra_offset).
  29. uint16_t ra_offset = 0;
  30. };
  31. // Parses |cfi_data| and creates a ArmCFITable that reads from it.
  32. // |cfi_data| is required to remain valid for the lifetime of the object.
  33. static std::unique_ptr<ArmCFITable> Parse(span<const uint8_t> cfi_data);
  34. ArmCFITable(span<const uint32_t> function_addresses,
  35. span<const uint16_t> entry_data_indices,
  36. span<const uint8_t> entry_data);
  37. ArmCFITable(const ArmCFITable&) = delete;
  38. ArmCFITable& operator=(const ArmCFITable&) = delete;
  39. ~ArmCFITable();
  40. // Finds the CFI row for the given |address| in terms of offset from the
  41. // start of the current binary. Concurrent calls are thread safe.
  42. absl::optional<FrameEntry> FindEntryForAddress(uintptr_t address) const;
  43. size_t GetTableSizeForTesting() const { return function_addresses_.size(); }
  44. private:
  45. // The UNW_INDEX table allows readers to map functions start addresses to
  46. // that function's respective entry in the UNW_DATA table.
  47. // - A function's start address is at 0x123, and
  48. // - function_addresses_[2] == 0x123, and
  49. // - entry_data_indices_[2] = 42, then
  50. // - entry_data_[42] is the corresponding entry in the UNW_DATA table for
  51. // the function with the start address of 0x123
  52. //
  53. // Note that function_addresses is sorted to facilitate easy lookup.
  54. const span<const uint32_t> function_addresses_;
  55. const span<const uint16_t> entry_data_indices_;
  56. // A reference to the UNW_DATA table. Each entry in the UNW_DATA table
  57. // corresponds to a function, which in turn corresponds to an array of
  58. // CFIDataRows. (see arm_cfi_reader.cc).
  59. const span<const uint8_t> entry_data_;
  60. };
  61. } // namespace base
  62. #endif // BASE_PROFILER_ARM_CFI_TABLE_H_