662 lines
20 KiB
C++
662 lines
20 KiB
C++
/*
|
|
* Interactive disassembler (IDA).
|
|
* Copyright (c) 1990-2021 Hex-Rays
|
|
* ALL RIGHTS RESERVED.
|
|
*
|
|
*/
|
|
|
|
/*! \file struct.hpp
|
|
|
|
\brief Structure type management (assembly level types)
|
|
|
|
*/
|
|
|
|
#ifndef _STRUCT_HPP
|
|
#define _STRUCT_HPP
|
|
#include <bytes.hpp>
|
|
|
|
#define STRUC_SEPARATOR '.' ///< structname.fieldname
|
|
|
|
/// Describes a member of an assembly level structure
|
|
class member_t
|
|
{
|
|
public:
|
|
tid_t id; ///< name(), cmt, rptcmt
|
|
ea_t soff; ///< start offset (for unions - number of the member 0..n)
|
|
ea_t eoff; ///< end offset
|
|
flags_t flag; ///< type+representation bits
|
|
// private:
|
|
uint32 props; ///< \ref MF_
|
|
/// \defgroup MF_ Struct member properties
|
|
/// Used by member_t::props
|
|
//@{
|
|
#define MF_OK 0x00000001 ///< is the member ok? (always yes)
|
|
#define MF_UNIMEM 0x00000002 ///< is a member of a union?
|
|
#define MF_HASUNI 0x00000004 ///< has members of type "union"?
|
|
#define MF_BYTIL 0x00000008 ///< the member was created due to the type system
|
|
#define MF_HASTI 0x00000010 ///< has type information?
|
|
#define MF_BASECLASS 0x00000020 ///< a special member representing base class
|
|
#define MF_DTOR 0x00000040 ///< a special member representing destructor
|
|
#define MF_DUPNAME 0x00000080 ///< duplicate name resolved with _N suffix (N==soff)
|
|
//@}
|
|
|
|
/// Is a member of a union?
|
|
bool unimem(void) const { return (props & MF_UNIMEM) != 0; }
|
|
/// Has members of type "union"?
|
|
bool has_union(void) const { return (props & MF_HASUNI) != 0; }
|
|
/// Was the member created due to the type system?
|
|
bool by_til(void) const { return (props & MF_BYTIL) != 0; }
|
|
/// Has type information?
|
|
bool has_ti(void) const { return (props & MF_HASTI) != 0; }
|
|
/// Is a base class member?
|
|
bool is_baseclass(void) const { return (props & MF_BASECLASS) != 0; }
|
|
/// Duplicate name was resolved during import?
|
|
bool is_dupname(void) const { return (props & MF_DUPNAME) != 0; }
|
|
/// Is a virtual destructor?
|
|
bool is_destructor(void) const { return (props & MF_DTOR) != 0; }
|
|
/// Get start offset (for unions - returns 0)
|
|
ea_t get_soff(void) const { return unimem() ? 0 : soff; }
|
|
};
|
|
|
|
/// Information about a structure type (assembly level)
|
|
//-V:struc_t:730 not all members of a class are initialized inside the constructor
|
|
class struc_t
|
|
{
|
|
protected:
|
|
struc_t(void) {} ///< plugins may not create struc_t instances. they should
|
|
///< use add_struc() and get_struc()
|
|
public:
|
|
tid_t id; ///< struct id
|
|
uint32 memqty; ///< number of members
|
|
member_t *members; ///< only defined members are stored here.
|
|
///< there may be gaps between members.
|
|
ushort age; ///< not used
|
|
uint32 props; ///< \ref SF_
|
|
/// \defgroup SF_ Structure properties
|
|
/// Used by struc_t::props
|
|
//@{
|
|
#define SF_VAR 0x00000001 ///< is variable size structure (varstruct)?
|
|
///< a variable size structure is one with
|
|
///< the zero size last member.
|
|
///< if the last member is a varstruct, then the current
|
|
///< structure is a varstruct too.
|
|
#define SF_UNION 0x00000002 ///< is a union?
|
|
///< varunions are prohibited!
|
|
#define SF_HASUNI 0x00000004 ///< has members of type "union"?
|
|
#define SF_NOLIST 0x00000008 ///< don't include in the chooser list
|
|
#define SF_TYPLIB 0x00000010 ///< the structure comes from type library
|
|
#define SF_HIDDEN 0x00000020 ///< the structure is collapsed
|
|
#define SF_FRAME 0x00000040 ///< the structure is a function frame
|
|
#define SF_ALIGN 0x00000F80 ///< alignment (shift amount: 0..31)
|
|
#define SF_GHOST 0x00001000 ///< ghost copy of a local type
|
|
//@}
|
|
|
|
/// Is variable size structure?
|
|
bool is_varstr(void) const { return (props & SF_VAR) != 0; }
|
|
/// Is a union?
|
|
bool is_union(void) const { return (props & SF_UNION) != 0; }
|
|
/// Has members of type "union"?
|
|
bool has_union(void) const { return (props & SF_HASUNI) != 0; }
|
|
/// Is included in chooser list?
|
|
/// Use \ref set_struc_listed to change the listed status
|
|
bool is_choosable(void) const { return (props & SF_NOLIST) == 0; }
|
|
/// Does structure come from a type library?
|
|
bool from_til(void) const { return (props & SF_TYPLIB) != 0; }
|
|
/// Is the structure collapsed?
|
|
/// Use \ref set_struc_hidden to change the hidden status
|
|
bool is_hidden(void) const { return (props & SF_HIDDEN) != 0; }
|
|
/// Is this structure a function frame?
|
|
bool is_frame(void) const { return (props & SF_FRAME) != 0; }
|
|
/// See #SF_ALIGN
|
|
int get_alignment(void) const { return (props & SF_ALIGN) >> 7; }
|
|
/// Is a ghost copy of a local type?
|
|
bool is_ghost(void) const { return (props & SF_GHOST) != 0; }
|
|
|
|
/// Do not use; use set_struc_align()
|
|
void set_alignment(int shift)
|
|
{
|
|
props &= ~SF_ALIGN;
|
|
props |= (shift << 7) & SF_ALIGN;
|
|
}
|
|
|
|
void set_ghost(bool _is_ghost) { setflag(props, SF_GHOST, _is_ghost); }
|
|
|
|
mutable int32 ordinal; ///< corresponding local type ordinal number
|
|
};
|
|
|
|
/// \name Internal structures list
|
|
/// IDA maintains an internal vector of known structures.
|
|
/// Use these functions to work with this vector.
|
|
//@{
|
|
|
|
/// Get number of known structures
|
|
|
|
idaman size_t ida_export get_struc_qty(void);
|
|
|
|
|
|
/// Get index of first structure.
|
|
/// \return #BADADDR if no known structures, 0 otherwise
|
|
|
|
idaman uval_t ida_export get_first_struc_idx(void);
|
|
|
|
|
|
/// Get index of last structure.
|
|
/// \return #BADADDR if no known structures, get_struc_qty()-1 otherwise
|
|
|
|
idaman uval_t ida_export get_last_struc_idx(void);
|
|
|
|
|
|
/// Get previous struct index.
|
|
/// \return #BADADDR if resulting index is negative, otherwise idx - 1
|
|
|
|
inline THREAD_SAFE uval_t get_prev_struc_idx(uval_t idx) { return idx == BADNODE ? idx : idx - 1; }
|
|
|
|
|
|
/// Get next struct index.
|
|
/// \return #BADADDR if resulting index is out of bounds, otherwise idx++
|
|
|
|
idaman uval_t ida_export get_next_struc_idx(uval_t idx);
|
|
|
|
|
|
/// Get internal number of the structure
|
|
|
|
idaman uval_t ida_export get_struc_idx(tid_t id);
|
|
|
|
|
|
/// Get struct id by struct number
|
|
|
|
idaman tid_t ida_export get_struc_by_idx(uval_t idx);
|
|
|
|
|
|
/// Get pointer to struct type info
|
|
|
|
idaman struc_t *ida_export get_struc(tid_t id);
|
|
|
|
//@}
|
|
|
|
|
|
/// Get struct id by name
|
|
|
|
inline tid_t get_struc_id(const char *name)
|
|
{
|
|
tid_t id = node2ea(netnode(name));
|
|
return get_struc(id) == NULL ? BADADDR : id;
|
|
}
|
|
|
|
|
|
/// Get struct name by id
|
|
/// \param[out] out buffer to hold the name
|
|
/// \param id struct id
|
|
/// \param flags \ref STRNFL_
|
|
|
|
idaman ssize_t ida_export get_struc_name(qstring *out, tid_t id, int flags=0);
|
|
|
|
/// \defgroup STRNFL_ Struct name flags
|
|
/// Passed as 'flags' parameter to get_struc_name()
|
|
//@{
|
|
#define STRNFL_REGEX 0x0001 ///< apply regular expressions to beautify the name
|
|
//@}
|
|
|
|
inline qstring get_struc_name(tid_t id, int flags=0)
|
|
{
|
|
qstring name;
|
|
get_struc_name(&name, id, flags);
|
|
return name;
|
|
}
|
|
|
|
/// Get struct comment
|
|
|
|
inline ssize_t get_struc_cmt(qstring *buf, tid_t id, bool repeatable) { return getnode(id).supstr(buf, repeatable != 0); }
|
|
|
|
|
|
/// Get struct size (also see get_struc_size(tid_t))
|
|
|
|
idaman asize_t ida_export get_struc_size(const struc_t *sptr);
|
|
|
|
/// Get struct size (also see get_struc_size(const struc_t *))
|
|
|
|
inline asize_t get_struc_size(tid_t id) { return get_struc_size(get_struc(id)); }
|
|
|
|
|
|
/// \name Struct offsets
|
|
/// \note for unions, soff == number of the current member
|
|
//@{
|
|
|
|
/// Get offset of member with largest offset less than 'offset'.
|
|
/// \return #BADADDR if no prev offset
|
|
|
|
idaman ea_t ida_export get_struc_prev_offset(const struc_t *sptr, ea_t offset);
|
|
|
|
|
|
/// Get offset of member with smallest offset larger than 'offset'.
|
|
/// \return #BADADDR if no next offset
|
|
|
|
idaman ea_t ida_export get_struc_next_offset(const struc_t *sptr, ea_t offset);
|
|
|
|
|
|
/// Get offset of last member.
|
|
/// \return #BADADDR if memqty == 0
|
|
|
|
idaman ea_t ida_export get_struc_last_offset(const struc_t *sptr);
|
|
|
|
|
|
/// Get offset of first member.
|
|
/// \return #BADADDR if memqty == 0
|
|
|
|
idaman ea_t ida_export get_struc_first_offset(const struc_t *sptr);
|
|
|
|
|
|
/// For unions: returns number of members, for structs: returns size of structure
|
|
|
|
inline ea_t get_max_offset(struc_t *sptr)
|
|
{
|
|
if ( sptr == NULL )
|
|
return 0; // just to avoid GPF
|
|
return sptr->is_union()
|
|
? sptr->memqty
|
|
: get_struc_size(sptr);
|
|
}
|
|
|
|
//@}
|
|
|
|
/// Is variable size structure?
|
|
|
|
inline bool is_varstr(tid_t id)
|
|
{
|
|
struc_t *sptr = get_struc(id);
|
|
return sptr != NULL && sptr->is_varstr();
|
|
}
|
|
|
|
/// Is a union?
|
|
|
|
inline bool is_union(tid_t id)
|
|
{
|
|
struc_t *sptr = get_struc(id);
|
|
return sptr != NULL && sptr->is_union();
|
|
}
|
|
|
|
|
|
/// Get containing structure of member by its full name "struct.field"
|
|
|
|
idaman struc_t *ida_export get_member_struc(const char *fullname);
|
|
|
|
|
|
/// Get child struct if member is a struct
|
|
|
|
idaman struc_t *ida_export get_sptr(const member_t *mptr);
|
|
|
|
|
|
/// Get member at given offset
|
|
|
|
idaman member_t *ida_export get_member(const struc_t *sptr, asize_t offset);
|
|
|
|
/// Get member id at given offset
|
|
|
|
inline tid_t get_member_id(const struc_t *sptr, asize_t offset)
|
|
{
|
|
member_t *mptr = get_member(sptr, offset);
|
|
return mptr != NULL ? mptr->id : BADADDR;
|
|
}
|
|
|
|
|
|
/// Get the innermost member at the given offset
|
|
/// \param[in] sptr the starting structure
|
|
/// \param[out] sptr the innermost structure
|
|
/// \param[in] offset offset into the starting structure
|
|
/// \param[out] offset remaining offset into the returned member
|
|
/// \retval a member in SPTR (it is not a structure) or 'nullptr'
|
|
|
|
idaman member_t *ida_export get_innermost_member(struc_t **sptr, asize_t *offset);
|
|
|
|
|
|
/// Get a member by its name, like "field44"
|
|
|
|
idaman member_t *ida_export get_member_by_name(const struc_t *sptr, const char *membername);
|
|
|
|
|
|
/// Get a member by its fully qualified name, "struct.field"
|
|
|
|
idaman member_t *ida_export get_member_by_fullname(struc_t **sptr_place, const char *fullname);
|
|
|
|
|
|
/// Get a member's fully qualified name, "struct.field"
|
|
|
|
inline ssize_t idaapi get_member_fullname(qstring *out, tid_t mid) { return getnode(mid).get_name(out); }
|
|
|
|
|
|
/// Get name of structure member
|
|
|
|
idaman ssize_t ida_export get_member_name(qstring *out, tid_t mid);
|
|
|
|
inline qstring get_member_name(tid_t mid)
|
|
{
|
|
qstring name;
|
|
get_member_name(&name, mid);
|
|
return name;
|
|
}
|
|
|
|
|
|
/// Get comment of structure member
|
|
|
|
inline ssize_t idaapi get_member_cmt(qstring *buf, tid_t mid, bool repeatable) { return getnode(mid).supstr(buf, repeatable != 0); }
|
|
|
|
|
|
/// Get size of structure member.
|
|
/// May return 0 for the last member of varstruct.
|
|
/// For union members, returns member_t::eoff.
|
|
|
|
inline asize_t get_member_size(const member_t *NONNULL mptr) { return mptr->unimem() ? mptr->eoff : (mptr->eoff - mptr->soff); }
|
|
|
|
|
|
/// Is variable size member?
|
|
|
|
idaman bool ida_export is_varmember(const member_t *mptr);
|
|
|
|
|
|
/// Get member that is most likely referenced by the specified offset.
|
|
/// Useful for offsets > sizeof(struct).
|
|
|
|
idaman member_t *ida_export get_best_fit_member(const struc_t *sptr, asize_t offset);
|
|
|
|
|
|
/// Get the next member idx, if it does not exist, return -1
|
|
|
|
idaman ssize_t ida_export get_next_member_idx(const struc_t *sptr, asize_t off);
|
|
|
|
|
|
/// Get the prev member idx, if it does not exist, return -1
|
|
|
|
idaman ssize_t ida_export get_prev_member_idx(const struc_t *sptr, asize_t off);
|
|
|
|
//--------------------------------------------------------------------------
|
|
// manipulation
|
|
|
|
/// Create a structure type.
|
|
/// if idx==#BADADDR then add as the last idx.
|
|
/// if name==NULL then a name will be generated "struct_%d".
|
|
|
|
idaman tid_t ida_export add_struc(uval_t idx, const char *name, bool is_union=false);
|
|
|
|
|
|
/// Delete a structure type
|
|
|
|
idaman bool ida_export del_struc(struc_t *sptr);
|
|
|
|
|
|
/// Set internal number of struct.
|
|
/// Also see get_struc_idx(), get_struc_by_idx().
|
|
|
|
idaman bool ida_export set_struc_idx(const struc_t *sptr, uval_t idx);
|
|
|
|
|
|
/// Set structure alignment (#SF_ALIGN)
|
|
|
|
idaman bool ida_export set_struc_align(struc_t *sptr, int shift);
|
|
|
|
|
|
/// Set structure name
|
|
|
|
idaman bool ida_export set_struc_name(tid_t id, const char *name);
|
|
|
|
|
|
/// Set structure comment
|
|
|
|
idaman bool ida_export set_struc_cmt(tid_t id, const char *cmt, bool repeatable);
|
|
|
|
|
|
/// Return values for add_struc_member()
|
|
enum struc_error_t
|
|
{
|
|
STRUC_ERROR_MEMBER_OK = 0, ///< success
|
|
STRUC_ERROR_MEMBER_NAME = -1, ///< already has member with this name (bad name)
|
|
STRUC_ERROR_MEMBER_OFFSET = -2, ///< already has member at this offset
|
|
STRUC_ERROR_MEMBER_SIZE = -3, ///< bad number of bytes or bad sizeof(type)
|
|
STRUC_ERROR_MEMBER_TINFO = -4, ///< bad typeid parameter
|
|
STRUC_ERROR_MEMBER_STRUCT = -5, ///< bad struct id (the 1st argument)
|
|
STRUC_ERROR_MEMBER_UNIVAR = -6, ///< unions can't have variable sized members
|
|
STRUC_ERROR_MEMBER_VARLAST = -7, ///< variable sized member should be the last member in the structure
|
|
STRUC_ERROR_MEMBER_NESTED = -8, ///< recursive structure nesting is forbidden
|
|
};
|
|
|
|
|
|
/// Add member to existing structure.
|
|
/// \param sptr structure to modify
|
|
/// \param fieldname if NULL, then "anonymous_#" name will be generated
|
|
/// \param offset #BADADDR means add to the end of structure
|
|
/// \param flag type + representation bits
|
|
/// \param mt additional info about member type.
|
|
/// must be present for
|
|
/// structs, offsets, enums, strings,
|
|
/// struct offsets.
|
|
/// \param nbytes if == 0 then the structure
|
|
/// will be a varstruct.
|
|
/// in this case the member should be
|
|
/// the last member in the structure
|
|
|
|
idaman struc_error_t ida_export add_struc_member(
|
|
struc_t *sptr,
|
|
const char *fieldname,
|
|
ea_t offset,
|
|
flags_t flag,
|
|
const opinfo_t *mt,
|
|
asize_t nbytes);
|
|
|
|
|
|
/// Delete member at given offset
|
|
|
|
idaman bool ida_export del_struc_member(struc_t *sptr, ea_t offset);
|
|
|
|
|
|
/// Delete members which occupy range of offsets (off1..off2).
|
|
/// \return number of deleted members or -1 on error
|
|
|
|
idaman int ida_export del_struc_members(struc_t *sptr, ea_t off1, ea_t off2);
|
|
|
|
|
|
/// Set name of member at given offset
|
|
|
|
idaman bool ida_export set_member_name(struc_t *sptr, ea_t offset,const char *name);
|
|
|
|
|
|
/// Set type of member at given offset (also see add_struc_member())
|
|
|
|
idaman bool ida_export set_member_type(struc_t *sptr, ea_t offset, flags_t flag,const opinfo_t *mt, asize_t nbytes);
|
|
|
|
|
|
/// Set member comment
|
|
|
|
idaman bool ida_export set_member_cmt(member_t *mptr,const char *cmt, bool repeatable);
|
|
|
|
|
|
/// Expand/Shrink structure type
|
|
|
|
idaman bool ida_export expand_struc(struc_t *sptr, ea_t offset, adiff_t delta, bool recalc=true);
|
|
|
|
|
|
/// Update struct information in the database (internal function)
|
|
|
|
idaman void ida_export save_struc(struc_t *sptr, bool may_update_ltypes=true);
|
|
|
|
|
|
/// Hide/unhide a struct type
|
|
inline void idaapi set_struc_hidden(struc_t *sptr, bool is_hidden)
|
|
{
|
|
setflag(sptr->props, SF_HIDDEN, is_hidden);
|
|
save_struc(sptr, false);
|
|
}
|
|
|
|
/// Add/remove a struct type from the struct list
|
|
inline void idaapi set_struc_listed(struc_t *sptr, bool is_listed)
|
|
{
|
|
setflag(sptr->props, SF_NOLIST, !is_listed);
|
|
save_struc(sptr, false);
|
|
}
|
|
|
|
/// Member type information (return values for set_member_tinfo())
|
|
enum smt_code_t
|
|
{
|
|
SMT_BADARG = -6, ///< bad parameters
|
|
SMT_NOCOMPAT = -5, ///< the new type is not compatible with the old type
|
|
SMT_WORSE = -4, ///< the new type is worse than the old type
|
|
SMT_SIZE = -3, ///< the new type is incompatible with the member size
|
|
SMT_ARRAY = -2, ///< arrays are forbidden as function arguments
|
|
SMT_OVERLAP = -1, ///< member would overlap with members that cannot be deleted
|
|
SMT_FAILED = 0, ///< failed to set new member type
|
|
SMT_OK = 1, ///< success: changed the member type
|
|
SMT_KEEP = 2, ///< no need to change the member type, the old type is better
|
|
};
|
|
|
|
|
|
/// Get tinfo for given member
|
|
|
|
idaman bool ida_export get_member_tinfo(tinfo_t *tif, const member_t *mptr);
|
|
|
|
|
|
/// Delete tinfo for given member
|
|
|
|
idaman bool ida_export del_member_tinfo(struc_t *sptr, member_t *mptr);
|
|
|
|
|
|
/// Set tinfo for given member.
|
|
/// \param sptr containing struct
|
|
/// \param mptr target member
|
|
/// \param memoff offset within member
|
|
/// \param tif type info
|
|
/// \param flags \ref SET_MEMTI_
|
|
|
|
idaman smt_code_t ida_export set_member_tinfo(
|
|
struc_t *sptr,
|
|
member_t *mptr,
|
|
uval_t memoff,
|
|
const tinfo_t &tif,
|
|
int flags);
|
|
|
|
/// \defgroup SET_MEMTI_ Set member tinfo flags
|
|
/// Passed as 'flags' parameter to set_member_tinfo()
|
|
//@{
|
|
#define SET_MEMTI_MAY_DESTROY 0x0001 ///< may destroy other members
|
|
#define SET_MEMTI_COMPATIBLE 0x0002 ///< new type must be compatible with the old
|
|
#define SET_MEMTI_FUNCARG 0x0004 ///< mptr is function argument (cannot create arrays)
|
|
#define SET_MEMTI_BYTIL 0x0008 ///< new type was created by the type subsystem
|
|
#define SET_MEMTI_USERTI 0x0010 ///< user-specified type
|
|
//@}
|
|
|
|
|
|
/// Try to get tinfo for given member - if failed, generate a tinfo using information about the
|
|
/// member id from the disassembly
|
|
|
|
idaman bool ida_export get_or_guess_member_tinfo(tinfo_t *tif, const member_t *mptr);
|
|
|
|
|
|
/// Get operand type info for member
|
|
|
|
inline opinfo_t *retrieve_member_info(opinfo_t *buf, const member_t *mptr)
|
|
{
|
|
if ( mptr == NULL )
|
|
return NULL;
|
|
return get_opinfo(buf, mptr->id, 0, mptr->flag);
|
|
}
|
|
|
|
|
|
/// Is member name prefixed with "anonymous"?
|
|
|
|
inline THREAD_SAFE bool is_anonymous_member_name(const char *name)
|
|
{
|
|
return name == NULL
|
|
|| strncmp(name, "anonymous", 9) == 0;
|
|
}
|
|
|
|
|
|
/// Is member name an auto-generated name?
|
|
|
|
inline THREAD_SAFE bool is_dummy_member_name(const char *name)
|
|
{
|
|
return name == NULL
|
|
|| strncmp(name, "arg_", 4) == 0
|
|
|| strncmp(name, "var_", 4) == 0
|
|
|| is_anonymous_member_name(name);
|
|
}
|
|
|
|
|
|
/// Check if the specified member id points to a struct member
|
|
|
|
inline member_t *idaapi get_member_by_id(
|
|
qstring *out_mname, // note: id 'out_mname' is important for SWiG
|
|
tid_t mid,
|
|
struc_t **sptr_place)
|
|
{
|
|
if ( get_member_fullname(out_mname, mid) > 0 )
|
|
return get_member_by_fullname(sptr_place, out_mname->begin());
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/// Check if the specified member id points to a struct member. convenience function
|
|
|
|
inline member_t *idaapi get_member_by_id(tid_t mid, struc_t **sptr_place=NULL)
|
|
{
|
|
qstring buf;
|
|
return get_member_by_id(&buf, mid, sptr_place);
|
|
}
|
|
|
|
|
|
/// Is a member id?
|
|
|
|
inline bool is_member_id(tid_t mid)
|
|
{
|
|
return get_member_by_id(mid) != NULL;
|
|
}
|
|
|
|
|
|
/// Is a special member with the name beginning with ' '?
|
|
|
|
idaman bool ida_export is_special_member(tid_t id);
|
|
|
|
|
|
/// Implements action to take when a field is visited with visit_stroff_fields()
|
|
struct ida_local struct_field_visitor_t
|
|
{
|
|
virtual int idaapi visit_field(struc_t *sptr, member_t *mptr) = 0;
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// Visit structure fields in a stroff expression or in a reference to a struct data variable.
|
|
/// This function can be used to enumerate all components of an expression like 'a.b.c'.
|
|
/// \param sfv visitor object
|
|
/// \param path struct path (path[0] contains the initial struct id)
|
|
/// \param plen len
|
|
/// \param[in,out] disp offset into structure
|
|
/// \param appzero should visit field at offset zero?
|
|
|
|
idaman flags_t ida_export visit_stroff_fields(
|
|
struct_field_visitor_t &sfv,
|
|
const tid_t *path,
|
|
int plen,
|
|
adiff_t *disp,
|
|
bool appzero);
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// Should display a structure offset expression as the structure size?
|
|
|
|
inline bool stroff_as_size(int plen, const struc_t *sptr, asize_t value)
|
|
{
|
|
return plen == 1
|
|
&& value > 0
|
|
&& sptr != NULL
|
|
&& !sptr->is_varstr()
|
|
&& value == get_struc_size(sptr);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// F U N C T I O N S F O R T H E K E R N E L
|
|
//-------------------------------------------------------------------------
|
|
|
|
///-------------------------------------------------------------------\cond
|
|
inline void save_structs(void) {}
|
|
///----------------------------------------------------------------\endcond
|
|
|
|
|
|
#endif // _STRUCT_HPP
|