1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
//===-- RegisterFlagsDetector_arm64.h ---------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
#include "lldb/Target/RegisterFlags.h"
#include "llvm/ADT/StringRef.h"
#include <functional>
namespace lldb_private {
struct RegisterInfo;
/// This class manages the storage and detection of register field information.
/// The same register may have different fields on different CPUs. This class
/// abstracts out the field detection process so we can use it on live processes
/// and core files.
///
/// The way to use this class is:
/// * Make an instance somewhere that will last as long as the debug session
/// (because your final register info will point to this instance).
/// * Read hardware capabilities from a core note, binary, prctl, etc.
/// * Pass those to DetectFields.
/// * Call UpdateRegisterInfo with your RegisterInfo to add pointers
/// to the detected fields for all registers listed in this class.
///
/// This must be done in that order, and you should ensure that if multiple
/// threads will reference the information, a mutex is used to make sure only
/// one calls DetectFields.
class Arm64RegisterFlagsDetector {
public:
/// For the registers listed in this class, detect which fields are
/// present. Must be called before UpdateRegisterInfos.
/// If called more than once, fields will be redetected each time from
/// scratch. If the target would not have this register at all, the list of
/// fields will be left empty.
void DetectFields(uint64_t hwcap, uint64_t hwcap2);
/// Add the field information of any registers named in this class,
/// to the relevant RegisterInfo instances. Note that this will be done
/// with a pointer to the instance of this class that you call this on, so
/// the lifetime of that instance must be at least that of the register info.
void UpdateRegisterInfo(const RegisterInfo *reg_info, uint32_t num_regs);
/// Returns true if field detection has been run at least once.
bool HasDetected() const { return m_has_detected; }
private:
using Fields = std::vector<RegisterFlags::Field>;
using DetectorFn = std::function<Fields(uint64_t, uint64_t)>;
static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2);
static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2);
static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2);
static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2);
static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2);
struct RegisterEntry {
RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
: m_name(name), m_flags(std::string(name) + "_flags", size, {}),
m_detector(detector) {}
llvm::StringRef m_name;
RegisterFlags m_flags;
DetectorFn m_detector;
} m_registers[5] = {
RegisterEntry("cpsr", 4, DetectCPSRFields),
RegisterEntry("fpsr", 4, DetectFPSRFields),
RegisterEntry("fpcr", 4, DetectFPCRFields),
RegisterEntry("mte_ctrl", 8, DetectMTECtrlFields),
RegisterEntry("svcr", 8, DetectSVCRFields),
};
// Becomes true once field detection has been run for all registers.
bool m_has_detected = false;
};
} // namespace lldb_private
#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
|