File indexing completed on 2024-05-12 04:39:44

0001 /*
0002     SPDX-FileCopyrightText: 2013 Vlas Puhov <vlas.puhov@mail.ru>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef _REGISTERCONTROLLER_H_
0008 #define _REGISTERCONTROLLER_H_
0009 
0010 #include <QHash>
0011 #include <QVector>
0012 #include <QObject>
0013 #include <QStringList>
0014 #include <QString>
0015 
0016 namespace KDevMI {
0017 namespace MI
0018 {
0019 struct ResultRecord;
0020 }
0021 
0022 class MIDebugSession;
0023 
0024 enum RegisterType {general, structured, flag, floatPoint};
0025 
0026 class GroupsName
0027 {
0028 public:
0029     QString name() const { return _name;}
0030     int index() const {return _index;}
0031     RegisterType type() const{return _type; }
0032     QString flagName() const{return _flagName;}
0033 
0034     bool operator==(const GroupsName& g) const {return _name == g.name();}
0035 
0036     GroupsName() {}
0037 
0038 private:
0039     GroupsName(const QString& name, int idx, RegisterType type = general, const QString& flag = QString()): _name(name), _index(idx), _type(type), _flagName(flag) {}
0040 
0041 private:
0042     QString _name;
0043     int _index = -1; ///Should be unique for each group for current architecture (0, 1...n).
0044     RegisterType _type = general;
0045     QString _flagName; ///Used only for flag registers.
0046 
0047     friend class IRegisterController;
0048     friend struct RegistersGroup;
0049 };
0050 
0051 enum Format {
0052     Binary,
0053     Octal,
0054     Decimal,
0055     Hexadecimal,
0056     Raw,
0057     Unsigned,
0058 
0059     LAST_FORMAT
0060 };
0061 
0062 enum Mode {
0063     natural,
0064 
0065     v4_float,
0066     v2_double,
0067     v4_int32,
0068     v2_int64,
0069 
0070     u32,
0071     u64,
0072     f32,
0073     f64,
0074 
0075     LAST_MODE
0076 };
0077 
0078 struct FormatsModes {
0079     QVector<Format> formats;
0080     QVector<Mode> modes;
0081 };
0082 
0083 ///Register in format: @p name, @p value - space separated list of values
0084 struct Register {
0085     Register() {}
0086     Register(const QString& _name, const QString& _value): name(_name), value(_value) {}
0087     QString name;
0088     QString value;
0089 };
0090 ///List of @p registers for @p groupName in @p format
0091 struct RegistersGroup {
0092     RegistersGroup()
0093 
0094     {}
0095 
0096     GroupsName groupName;
0097     QVector<Register> registers;
0098     Format format = Binary; ///<Current format
0099     bool flag = false; ///<true if this group is flags group.
0100 };
0101 
0102 struct FlagRegister {
0103     QStringList flags;
0104     QStringList bits;
0105     QString registerName;
0106     GroupsName groupName;
0107 };
0108 
0109 /** @brief Class for managing registers: it can retrieve, change and send registers back to the debugger.*/
0110 class IRegisterController : public QObject
0111 {
0112     Q_OBJECT
0113 
0114 public:
0115     ///Sets session @p debugSession to send commands to.
0116     void setSession(MIDebugSession* debugSession);
0117 
0118     ///There'll be at least 2 groups: "General" and "Flags", also "XMM", "FPU", "Segment" for x86, x86_64 architectures.
0119     virtual QVector<GroupsName> namesOfRegisterGroups() const = 0;
0120 
0121     ///Returns all supported formats for @p group (bin, dec, hex ...)
0122     QVector<Format> formats(const GroupsName& group);
0123 
0124     ///Sets current format for the @p group, if format is supported. Does nothing otherwise.
0125     void setFormat(Format f, const GroupsName& group);
0126 
0127     ///Returns all supported modes for @p group (i.e. how to display group: 2 int, 4 float or other number of columns)
0128     QVector<Mode> modes(const GroupsName& group);
0129 
0130     ///Sets current mode for the @p group, if mode is supported. Does nothing otherwise.
0131     void setMode(Mode m, const GroupsName& group);
0132 
0133 Q_SIGNALS:
0134     ///Emits @p group with updated registers.
0135     void registersChanged(const RegistersGroup& g);
0136 
0137 public Q_SLOTS:
0138     ///Updates registers in @p group. If @p group is empty - updates all registers.
0139     virtual void updateRegisters(const GroupsName& group = GroupsName());
0140 
0141     ///Sends updated register's @p reg value to the debugger.
0142     virtual void setRegisterValue(const Register& reg);
0143 
0144 protected:
0145     explicit IRegisterController(MIDebugSession* debugSession = nullptr, QObject* parent = nullptr);
0146 
0147     ///Returns registers from the @p group, or empty registers group if @p group is invalid.
0148     virtual RegistersGroup registersFromGroup(const GroupsName& group) const = 0;
0149 
0150     ///Sets value for @p register from @p group.
0151     virtual void setRegisterValueForGroup(const GroupsName& group, const Register& reg) = 0;
0152 
0153     ///Returns names of all registers for @p group.
0154     virtual QStringList registerNamesForGroup(const GroupsName& group) const = 0;
0155 
0156     /**Updates value for each register in the group.
0157      * @param [out] registers Registers which values should be updated.
0158      */
0159     virtual void updateValuesForRegisters(RegistersGroup* registers) const;
0160 
0161     ///Returns value for the given @p name, empty string if the name is incorrect or there is no registers yet.
0162     QString registerValue(const QString& name) const;
0163 
0164     /** Sets a flag register.
0165      * @param reg register to set
0166      * @param flag flag register @p reg belongs to.
0167      */
0168     void setFlagRegister(const Register& reg, const FlagRegister& flag);
0169 
0170     ///Sets new value for register @p reg, from group @p group.
0171     void setGeneralRegister(const Register& reg, const GroupsName& group);
0172 
0173     ///Sets new value for structured register(XMM, VFP quad and other) @p reg, from group @p group.
0174     void setStructuredRegister(const Register& reg, const GroupsName& group);
0175 
0176     ///Updates values in @p flagsGroup for @p flagRegister.
0177     void updateFlagValues(RegistersGroup* flagsGroup, const FlagRegister& flagRegister) const;
0178 
0179     ///Returns group that given register belongs to.
0180     GroupsName groupForRegisterName(const QString& name) const;
0181 
0182     ///Initializes registers, that is gets names of all available registers. Returns true is succeed.
0183     bool initializeRegisters();
0184 
0185     GroupsName createGroupName(const QString& name, int idx, RegisterType t = general, const QString& flag = QString()) const;
0186 
0187     ///Returns register's number for @p name.
0188     QString numberForName(const QString& name) const;
0189 
0190 public:
0191     ~IRegisterController() override;
0192 
0193 private :
0194     ///Handles initialization of register's names.
0195     void registerNamesHandler(const MI::ResultRecord& r);
0196 
0197     ///Parses new values for general registers from @p r and updates it in m_registers.
0198     ///Emits registersChanged signal.
0199     void generalRegistersHandler(const MI::ResultRecord& r);
0200 
0201     ///Parses new values for structured registers from @p r and updates it in m_registers.
0202     ///Emits registersChanged signal.
0203     virtual void structuredRegistersHandler(const MI::ResultRecord& r);
0204 
0205 private:
0206 
0207     ///Groups that should be updated(emitted @p registersInGroupChanged signal), if empty - all.
0208     QVector<GroupsName> m_pendingGroups;
0209 
0210 protected:
0211     ///Register names as it sees debugger (in format: number, name).
0212     QVector<QString > m_rawRegisterNames;
0213 
0214     ///Registers in format: name, value
0215     QHash<QString, QString > m_registers;
0216 
0217     ///Supported formats and modes for each register's group. First format/mode is current.
0218     QVector<FormatsModes > m_formatsModes;
0219 
0220     ///Current debug session;
0221     MIDebugSession* m_debugSession;
0222 };
0223 
0224 } // end of namespace KDevMI
0225 
0226 Q_DECLARE_TYPEINFO(KDevMI::Register, Q_MOVABLE_TYPE);
0227 Q_DECLARE_TYPEINFO(KDevMI::RegistersGroup, Q_MOVABLE_TYPE);
0228 Q_DECLARE_TYPEINFO(KDevMI::FlagRegister, Q_MOVABLE_TYPE);
0229 Q_DECLARE_TYPEINFO(KDevMI::GroupsName, Q_MOVABLE_TYPE);
0230 Q_DECLARE_TYPEINFO(KDevMI::FormatsModes, Q_MOVABLE_TYPE);
0231 
0232 #endif