76 lines
2.8 KiB
C
76 lines
2.8 KiB
C
|
// 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 <memory>
|
||
|
|
||
|
#include "base/containers/buffer_iterator.h"
|
||
|
#include "base/containers/span.h"
|
||
|
#include "base/macros.h"
|
||
|
#include "base/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<ArmCFITable> Parse(span<const uint8_t> cfi_data);
|
||
|
|
||
|
ArmCFITable(span<const uint32_t> function_addresses,
|
||
|
span<const uint16_t> entry_data_indices,
|
||
|
span<const uint8_t> entry_data);
|
||
|
~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.
|
||
|
Optional<FrameEntry> 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<const uint32_t> function_addresses_;
|
||
|
const span<const uint16_t> 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<const uint8_t> entry_data_;
|
||
|
|
||
|
DISALLOW_COPY_AND_ASSIGN(ArmCFITable);
|
||
|
};
|
||
|
|
||
|
} // namespace base
|
||
|
|
||
|
#endif // BASE_PROFILER_ARM_CFI_TABLE_H_
|