/* * Interactive disassembler (IDA). * Copyright (c) 1990-2021 Hex-Rays * ALL RIGHTS RESERVED. * * Enums and bitfields * Bitfields will be abbreviated as "bf". * */ #ifndef _ENUM_HPP #define _ENUM_HPP #include /*! \file enum.hpp \brief Assembly level enum management Enums and bitfields are represented as ::enum_t. */ typedef tid_t enum_t; ///< Enums and bitfields typedef uval_t bmask_t; ///< unsigned value that describes a bitmask ///< a bit mask is 32/64 bits. #define DEFMASK (bmask_t(-1)) ///< default bitmask typedef uval_t const_t; ///< members of enums /// Max number of identical constants allowed for one enum type const uchar MAX_ENUM_SERIAL = 255; /// Get number of declared ::enum_t types idaman size_t ida_export get_enum_qty(void); /// Get enum by its index in the list of enums (0..get_enum_qty()-1). idaman enum_t ida_export getn_enum(size_t idx); /// Get the index in the list of enums idaman uval_t ida_export get_enum_idx(enum_t id); /// Get enum by name idaman enum_t ida_export get_enum(const char *name); /// Is enum a bitfield? /// (otherwise - plain enum, no bitmasks except for #DEFMASK are allowed) idaman bool ida_export is_bf(enum_t id); /// Is enum collapsed? idaman bool ida_export is_enum_hidden(enum_t id); /// Collapse enum idaman bool ida_export set_enum_hidden(enum_t id, bool hidden); /// Does enum come from type library? idaman bool ida_export is_enum_fromtil(enum_t id); /// Specify that enum comes from a type library idaman bool ida_export set_enum_fromtil(enum_t id, bool fromtil); /// Is a ghost copy of a local type? idaman bool ida_export is_ghost_enum(enum_t id); /// Specify that enum is a ghost copy of a local type idaman bool ida_export set_enum_ghost(enum_t id, bool ghost); /// Get name of enum idaman ssize_t ida_export get_enum_name(qstring *out, enum_t id); /// Get name of enum /// \param[out] out buffer to hold the name /// \param id enum id /// \param flags \ref ENFL_ idaman ssize_t ida_export get_enum_name2(qstring *out, enum_t id, int flags=0); /// \defgroup ENFL_ Enum name flags /// Passed as 'flags' parameter to get_enum_name() //@{ #define ENFL_REGEX 0x0001 ///< apply regular expressions to beautify the name //@} inline qstring get_enum_name(tid_t id, int flags=0) { qstring name; get_enum_name2(&name, id, flags); return name; } /// Get the width of a enum element /// allowed values: 0 (unspecified),1,2,4,8,16,32,64 idaman size_t ida_export get_enum_width(enum_t id); /// See comment for get_enum_width() idaman bool ida_export set_enum_width(enum_t id, int width); /// Get enum comment idaman ssize_t ida_export get_enum_cmt(qstring *buf, enum_t id, bool repeatable); /// Get the number of the members of the enum idaman size_t ida_export get_enum_size(enum_t id); /// Get flags determining the representation of the enum. /// (currently they define the numeric base: octal, decimal, hex, bin) and signness. idaman flags_t ida_export get_enum_flag(enum_t id); /// Get a reference to an enum member by its name idaman const_t ida_export get_enum_member_by_name(const char *name); /// Get value of an enum member idaman uval_t ida_export get_enum_member_value(const_t id); /// Get the parent enum of an enum member idaman enum_t ida_export get_enum_member_enum(const_t id); /// Get bitmask of an enum member idaman bmask_t ida_export get_enum_member_bmask(const_t id); /// Find an enum member by enum, value and bitmask /// \note if serial -1, return a member with any serial idaman const_t ida_export get_enum_member(enum_t id, uval_t value, int serial, bmask_t mask); /// \name Access to all used bitmasks in an enum //@{ /// Get first bitmask in the enum (bitfield) /// /// \param enum_id id of enum (bitfield) /// \return the smallest bitmask for enum, or DEFMASK /// idaman bmask_t ida_export get_first_bmask(enum_t id); /// Get last bitmask in the enum (bitfield) /// /// \param enum_id id of enum /// \return the biggest bitmask for enum, or DEFMASK idaman bmask_t ida_export get_last_bmask(enum_t id); /// Get next bitmask in the enum (bitfield) /// /// \param enum_id id of enum /// \param value the current bitmask /// \return value of a bitmask with value higher than the specified value, or DEFMASK idaman bmask_t ida_export get_next_bmask(enum_t id, bmask_t bmask); /// Get prev bitmask in the enum (bitfield) /// /// \param enum_id id of enum /// \param value the current bitmask /// \return value of a bitmask with value lower than the specified value, or DEFMASK idaman bmask_t ida_export get_prev_bmask(enum_t id, bmask_t bmask); //@} /// \name Access to all enum members with specified bitmask /// \note these functions return values, not ::const_t! //@{ idaman uval_t ida_export get_first_enum_member(enum_t id, bmask_t bmask=DEFMASK); idaman uval_t ida_export get_last_enum_member(enum_t id, bmask_t bmask=DEFMASK); idaman uval_t ida_export get_next_enum_member(enum_t id, uval_t value, bmask_t bmask=DEFMASK); idaman uval_t ida_export get_prev_enum_member(enum_t id, uval_t value, bmask_t bmask=DEFMASK); //@} /// Get name of an enum member by const_t idaman ssize_t ida_export get_enum_member_name(qstring *out, const_t id); /// Get enum member's comment idaman ssize_t ida_export get_enum_member_cmt(qstring *buf, const_t id, bool repeatable); /// \name Access to all enum members with specified value and mask /// A sample loop looks like this: /// \code /// const_t main_cid; /// uchar serial; /// for ( const_t cid=main_cid=get_first_serial_enum_member(&serial, id, v, mask); /// cid != BADNODE; /// cid = get_next_serial_enum_member(&serial, main_cid) ) /// { /// ... /// } /// \endcode /// The 'out_serial' argument of get_first_serial_enum_member/get_last_serial_enum_member can be NULL. /// The 'in_out_serial' is required for the other functions. //@{ idaman const_t ida_export get_first_serial_enum_member(uchar *out_serial, enum_t id, uval_t value, bmask_t bmask); idaman const_t ida_export get_last_serial_enum_member(uchar *out_serial, enum_t id, uval_t value, bmask_t bmask); idaman const_t ida_export get_next_serial_enum_member(uchar *in_out_serial, const_t first_cid); idaman const_t ida_export get_prev_serial_enum_member(uchar *in_out_serial, const_t first_cid); //@} /// Enum member visitor - see for_all_enum_members(). /// Derive your visitor from this class. struct enum_member_visitor_t { /// Implements action to take when enum member is visited. /// \return nonzero to stop the iteration virtual int idaapi visit_enum_member(const_t cid, uval_t value) = 0; }; /// Visit all members of a given enum idaman int ida_export for_all_enum_members(enum_t id, enum_member_visitor_t &cv); /// Get serial number of an enum member idaman uchar ida_export get_enum_member_serial(const_t cid); /// Get corresponding type ordinal number idaman int32 ida_export get_enum_type_ordinal(enum_t id); /// Set corresponding type ordinal number idaman void ida_export set_enum_type_ordinal(enum_t id, int32 ord); //-------------------------------------------------------------------------- // MANIPULATION /// Add new enum type. /// - if idx==#BADADDR then add as the last idx /// - if name==NULL then generate a unique name "enum_%d" idaman enum_t ida_export add_enum(size_t idx, const char *name, flags_t flag); /// Delete an enum type idaman void ida_export del_enum(enum_t id); /// Set serial number of enum. /// Also see get_enum_idx(). idaman bool ida_export set_enum_idx(enum_t id, size_t idx); /// Set 'bitfield' bit of enum (i.e. convert it to a bitfield) idaman bool ida_export set_enum_bf(enum_t id, bool bf); /// Set name of enum type idaman bool ida_export set_enum_name(enum_t id,const char *name); /// Set comment for enum type idaman bool ida_export set_enum_cmt(enum_t id,const char *cmt,bool repeatable); /// Set data representation flags idaman bool ida_export set_enum_flag(enum_t id, flags_t flag); /// Add member to enum type. /// \return 0 if ok, otherwise one of \ref ENUM_MEMBER_ idaman int ida_export add_enum_member( enum_t id, const char *name, uval_t value, bmask_t bmask=DEFMASK); /// \defgroup ENUM_MEMBER_ Add enum member result codes /// Return values for add_enum_member() //@{ #define ENUM_MEMBER_ERROR_NAME 1 ///< already have member with this name (bad name) #define ENUM_MEMBER_ERROR_VALUE 2 ///< already have 256 members with this value #define ENUM_MEMBER_ERROR_ENUM 3 ///< bad enum id #define ENUM_MEMBER_ERROR_MASK 4 ///< bad bmask #define ENUM_MEMBER_ERROR_ILLV 5 ///< bad bmask and value combination (~bmask & value != 0) //@} /// Delete member of enum type idaman bool ida_export del_enum_member(enum_t id, uval_t value, uchar serial, bmask_t bmask); /// Set name of enum member idaman bool ida_export set_enum_member_name(const_t id, const char *name); /// Set comment for enum member inline bool set_enum_member_cmt(const_t id, const char *cmt, bool repeatable) { return set_enum_cmt(id, cmt, repeatable); } /// Is bitmask one bit? inline THREAD_SAFE bool is_one_bit_mask(bmask_t mask) { return (mask & (mask-1)) == 0; } /// \name Work with the bitmask name & comment //@{ idaman bool ida_export set_bmask_name(enum_t id, bmask_t bmask, const char *name); idaman ssize_t ida_export get_bmask_name(qstring *out, enum_t id, bmask_t bmask); idaman bool ida_export set_bmask_cmt(enum_t id, bmask_t bmask, const char *cmt, bool repeatable); idaman ssize_t ida_export get_bmask_cmt(qstring *buf, enum_t id, bmask_t bmask, bool repeatable); //@} #endif // _ENUM_HPP