Module index

# Module `ida_frame`

Routines to manipulate function stack frames, stack variables, register variables and local labels.

The frame is represented as a structure: +------------------------------------------------+ | function arguments | +------------------------------------------------+ | return address (isn't stored in func_t) | +------------------------------------------------+ | saved registers (SI, DI, etc - func_t::frregs) | +------------------------------------------------+ <- typical BP | | | | | | func_t::fpd | | | | | <- real BP | local variables (func_t::frsize) | | | | | +------------------------------------------------+ <- SP

To access the structure of a function frame, use: * tinfo_t::get_func_frame(const func_t pfn) (the preferred way) * get_func_frame(tinfo_t out, const func_t *pfn)

## Global variables

`var REGVAR_ERROR_ARG`

  function arguments are bad

`var REGVAR_ERROR_NAME`

  the provided name(s) can't be accepted

`var REGVAR_ERROR_OK`

  all ok

`var REGVAR_ERROR_RANGE`

  the definition range is bad

`var STKVAR_VALID_SIZE`

  x.dtyp contains correct variable type (for insns like 'lea' this bit must be off). In general, dr_O references do not allow to determine the variable size

## Functions

`def add_auto_stkpnt(pfn: func_t *, ea: ea_t, delta: sval_t)`

  add_auto_stkpnt(pfn, ea, delta) -> bool Add automatic SP register change point.

  @param pfn: (C++: func_t *) pointer to the function. may be nullptr. @param ea: (C++: ea_t) linear address where SP changes. usually this is the end of the instruction which modifies the stack pointer ( insn_t::ea+ insn_t::size) @param delta: (C++: sval_t) difference between old and new values of SP @return: success

`def add_frame(pfn: func_t *, frsize: sval_t, frregs: ushort, argsize: asize_t)`

  add_frame(pfn, frsize, frregs, argsize) -> bool Add function frame.

  @param pfn: (C++: func_t *) pointer to function structure @param frsize: (C++: sval_t) size of function local variables @param frregs: (C++: ushort) size of saved registers @param argsize: (C++: asize_t) size of function arguments range which will be purged upon return. this parameter is used for __stdcall and __pascal calling conventions. for other calling conventions please pass 0. @retval 1: ok @retval 0: failed (no function, frame already exists)

`def add_frame_member(pfn: func_t const *, name: char const *, offset: uval_t, tif: tinfo_t, repr: value_repr_t = None, etf_flags: uint = 0)`

  add_frame_member(pfn, name, offset, tif, repr=None, etf_flags=0) -> bool Add member to the frame type

  @param pfn: (C++: const func_t ) pointer to function @param name: (C++: const char ) variable name, nullptr means autogenerate a name @param offset: (C++: uval_t) member offset in the frame structure, in bytes @param tif: (C++: const tinfo_t &) variable type @param repr: (C++: const struct value_repr_t *) variable representation @param etf_flags: (C++: uint) @see: type changing flags @return: success

`def add_regvar(pfn: func_t *, ea1: ea_t, ea2: ea_t, canon: char const *, user: char const *, cmt: char const *)`

  add_regvar(pfn, ea1, ea2, canon, user, cmt) -> int Define a register variable.

  @param pfn: (C++: func_t ) function in which the definition will be created @param ea1: (C++: ea_t) ,ea2: range of addresses within the function where the definition will be used @param canon: (C++: const char ) name of a general register @param canon: (C++: const char ) name of a general register @param user: (C++: const char ) user-defined name for the register @param cmt: (C++: const char *) comment for the definition @return: Register variable error codes

`def add_user_stkpnt(ea: ea_t, delta: sval_t)`

  add_user_stkpnt(ea, delta) -> bool Add user-defined SP register change point.

  @param ea: (C++: ea_t) linear address where SP changes @param delta: (C++: sval_t) difference between old and new values of SP @return: success

`def build_stkvar_name(pfn: func_t const *, v: sval_t)`

  build_stkvar_name(pfn, v) -> str Build automatic stack variable name.

  @param pfn: (C++: const func_t *) pointer to function (can't be nullptr!) @param v: (C++: sval_t) value of variable offset @return: length of stack variable name or -1

`def build_stkvar_xrefs(out: xreflist_t, pfn: func_t *, start_offset: uval_t, end_offset: uval_t)`

  build_stkvar_xrefs(out, pfn, start_offset, end_offset) Fill 'out' with a list of all the xrefs made from function 'pfn' to specified range of the pfn's stack frame.

  @param out: (C++: xreflist_t ) the list of xrefs to fill. @param pfn: (C++: func_t ) the function to scan. @param start_offset: (C++: uval_t) start frame structure offset, in bytes @param end_offset: (C++: uval_t) end frame structure offset, in bytes

`def calc_frame_offset(pfn: func_t *, off: sval_t, insn: insn_t const * = None, op: op_t const * = None)`

  calc_frame_offset(pfn, off, insn=None, op=None) -> sval_t Calculate the offset of stack variable in the frame.

  @param pfn: (C++: func_t ) pointer to function (cannot be nullptr) @param off: (C++: sval_t) the offset relative to stack pointer or frame pointer @param insn: (C++: const insn_t ) the instruction @param op: (C++: const op_t *) the operand @return: the offset in the frame

`def calc_stkvar_struc_offset(pfn: func_t *, insn: insn_t const &, n: int)`

  calc_stkvar_struc_offset(pfn, insn, n) -> ea_t Calculate offset of stack variable in the frame structure.

  @param pfn: (C++: func_t *) pointer to function (cannot be nullptr) @param insn: (C++: const insn_t &) the instruction @param n: (C++: int) 0..UA_MAXOP-1 operand number -1 if error, return BADADDR @return: BADADDR if some error (issue a warning if stack frame is bad)

`def define_stkvar(pfn: func_t *, name: char const *, off: sval_t, tif: tinfo_t, repr: value_repr_t = None)`

  define_stkvar(pfn, name, off, tif, repr=None) -> bool Define/redefine a stack variable.

  @param pfn: (C++: func_t ) pointer to function @param name: (C++: const char ) variable name, nullptr means autogenerate a name @param off: (C++: sval_t) offset of the stack variable in the frame. negative values denote local variables, positive - function arguments. @param tif: (C++: const tinfo_t &) variable type @param repr: (C++: const struct value_repr_t *) variable representation @return: success

`def del_frame(pfn: func_t *)`

  del_frame(pfn) -> bool Delete a function frame.

  @param pfn: (C++: func_t *) pointer to function structure @return: success

`def del_regvar(pfn: func_t *, ea1: ea_t, ea2: ea_t, canon: char const *)`

  del_regvar(pfn, ea1, ea2, canon) -> int Delete a register variable definition.

  @param pfn: (C++: func_t ) function in question @param ea1: (C++: ea_t) ,ea2: range of addresses within the function where the definition holds @param canon: (C++: const char ) name of a general register @param canon: (C++: const char *) name of a general register @return: Register variable error codes

`def del_stkpnt(pfn: func_t *, ea: ea_t)`

  del_stkpnt(pfn, ea) -> bool Delete SP register change point.

  @param pfn: (C++: func_t *) pointer to the function. may be nullptr. @param ea: (C++: ea_t) linear address @return: success

`def delete_frame_members(pfn: func_t const *, start_offset: uval_t, end_offset: uval_t)`

  delete_frame_members(pfn, start_offset, end_offset) -> bool Delete frame members

  @param pfn: (C++: const func_t *) pointer to function @param start_offset: (C++: uval_t) member offset to start deletion from, in bytes @param end_offset: (C++: uval_t) member offset which not included in the deletion, in bytes @return: success

`def find_regvar(*args)`

  find_regvar(pfn, ea1, ea2, canon, user) -> regvar_t Find a register variable definition.

  @param pfn: (C++: func_t ) function in question @param ea1: ea_t @param canon: (C++: const char ) name of a general register @param canon: (C++: const char *) name of a general register @param user: char const *

  @return: nullptr-not found, otherwise ptr to regvar_t find_regvar(pfn, ea, canon) -> regvar_t

  @param pfn: func_t * @param ea: ea_t @param canon: char const *

`def frame_off_args(pfn: func_t const *)`

  frame_off_args(pfn) -> ea_t Get starting address of arguments section.

  @param pfn: (C++: const func_t *) func_t const *

`def frame_off_lvars(pfn: func_t const *)`

  frame_off_lvars(pfn) -> ea_t Get start address of local variables section.

  @param pfn: (C++: const func_t *) func_t const *

`def frame_off_retaddr(pfn: func_t const *)`

  frame_off_retaddr(pfn) -> ea_t Get starting address of return address section.

  @param pfn: (C++: const func_t *) func_t const *

`def frame_off_savregs(pfn: func_t const *)`

  frame_off_savregs(pfn) -> ea_t Get starting address of saved registers section.

  @param pfn: (C++: const func_t *) func_t const *

`def free_regvar(v: regvar_t)`

  free_regvar(v)

  @param v: regvar_t *

`def get_effective_spd(pfn: func_t *, ea: ea_t)`

  get_effective_spd(pfn, ea) -> sval_t Get effective difference between the initial and current values of ESP. This function returns the sp-diff used by the instruction. The difference between get_spd() and get_effective_spd() is present only for instructions like "pop [esp+N]": they modify sp and use the modified value.

  @param pfn: (C++: func_t *) pointer to the function. may be nullptr. @param ea: (C++: ea_t) linear address @return: 0 or the difference, usually a negative number

`def get_frame_part(range: range_t, pfn: func_t const *, part: frame_part_t)`

  get_frame_part(range, pfn, part) Get offsets of the frame part in the frame.

  @param range: (C++: range_t ) pointer to the output buffer with the frame part start/end(exclusive) offsets, can't be nullptr @param pfn: (C++: const func_t ) pointer to function structure, can't be nullptr @param part: (C++: frame_part_t) frame part

`def get_frame_retsize(pfn: func_t const *)`

  get_frame_retsize(pfn) -> int Get size of function return address.

  @param pfn: (C++: const func_t *) pointer to function structure, can't be nullptr

`def get_frame_size(pfn: func_t const *)`

  get_frame_size(pfn) -> asize_t Get full size of a function frame. This function takes into account size of local variables + size of saved registers + size of return address + number of purged bytes. The purged bytes correspond to the arguments of the functions with __stdcall and __fastcall calling conventions.

  @param pfn: (C++: const func_t *) pointer to function structure, may be nullptr @return: size of frame in bytes or zero

`def get_func_frame(out: tinfo_t, pfn: func_t const *)`

  get_func_frame(out, pfn) -> bool

  @param out: tinfo_t * @param pfn: func_t const *

`def get_sp_delta(pfn: func_t *, ea: ea_t)`

  get_sp_delta(pfn, ea) -> sval_t Get modification of SP made at the specified location

  @param pfn: (C++: func_t *) pointer to the function. may be nullptr. @param ea: (C++: ea_t) linear address @return: 0 if the specified location doesn't contain a SP change point. otherwise return delta of SP modification.

`def get_spd(pfn: func_t *, ea: ea_t)`

  get_spd(pfn, ea) -> sval_t Get difference between the initial and current values of ESP.

  @param pfn: (C++: func_t *) pointer to the function. may be nullptr. @param ea: (C++: ea_t) linear address of the instruction @return: 0 or the difference, usually a negative number. returns the sp-diff before executing the instruction.

`def has_regvar(pfn: func_t *, ea: ea_t)`

  has_regvar(pfn, ea) -> bool Is there a register variable definition?

  @param pfn: (C++: func_t *) function in question @param ea: (C++: ea_t) current address

`def is_anonymous_member_name(name: char const *)`

  is_anonymous_member_name(name) -> bool Is member name prefixed with "anonymous"?

  @param name: (C++: const char *) char const *

`def is_dummy_member_name(name: char const *)`

  is_dummy_member_name(name) -> bool Is member name an auto-generated name?

  @param name: (C++: const char *) char const *

`def is_funcarg_off(pfn: func_t const *, frameoff: uval_t)`

  is_funcarg_off(pfn, frameoff) -> bool

  @param pfn: func_t const * @param frameoff: uval_t

`def is_special_frame_member(tid: tid_t)`

  is_special_frame_member(tid) -> bool Is stkvar with TID the return address slot or the saved registers slot ?

  @param tid: (C++: tid_t) frame member type id return address or saved registers member?

`def lvar_off(pfn: func_t const *, frameoff: uval_t)`

  lvar_off(pfn, frameoff) -> sval_t

  @param pfn: func_t const * @param frameoff: uval_t

`def recalc_spd(cur_ea: ea_t)`

  recalc_spd(cur_ea) -> bool Recalculate SP delta for an instruction that stops execution. The next instruction is not reached from the current instruction. We need to recalculate SP for the next instruction.

  This function will create a new automatic SP register change point if necessary. It should be called from the emulator (emu.cpp) when auto_state == AU_USED if the current instruction doesn't pass the execution flow to the next instruction.

  @param cur_ea: (C++: ea_t) linear address of the current instruction @retval 1: new stkpnt is added @retval 0: nothing is changed

`def recalc_spd_for_basic_block(pfn: func_t *, cur_ea: ea_t)`

  recalc_spd_for_basic_block(pfn, cur_ea) -> bool Recalculate SP delta for the current instruction. The typical code snippet to calculate SP delta in a proc module is:

  if ( may_trace_sp() && pfn != nullptr ) if ( !recalc_spd_for_basic_block(pfn, insn.ea) ) trace_sp(pfn, insn);

  where trace_sp() is a typical name for a function that emulates the SP change of an instruction.

  @param pfn: (C++: func_t *) pointer to the function @param cur_ea: (C++: ea_t) linear address of the current instruction @retval true: the cumulative SP delta is set @retval false: the instruction at CUR_EA passes flow to the next instruction. SP delta must be set as a result of emulating the current instruction.

`def rename_regvar(pfn: func_t *, v: regvar_t, user: char const *)`

  rename_regvar(pfn, v, user) -> int Rename a register variable.

  @param pfn: (C++: func_t ) function in question @param v: (C++: regvar_t ) variable to rename @param user: (C++: const char *) new user-defined name for the register @return: Register variable error codes

`def set_auto_spd(pfn: func_t *, ea: ea_t, new_spd: sval_t)`

  set_auto_spd(pfn, ea, new_spd) -> bool Add such an automatic SP register change point so that at EA the new cumulative SP delta (that is, the difference between the initial and current values of SP) would be equal to NEW_SPD.

  @param pfn: (C++: func_t *) pointer to the function. may be nullptr. @param ea: (C++: ea_t) linear address of the instruction @param new_spd: (C++: sval_t) new value of the cumulative SP delta @return: success

`def set_frame_member_type(pfn: func_t const *, offset: uval_t, tif: tinfo_t, repr: value_repr_t = None, etf_flags: uint = 0)`

  set_frame_member_type(pfn, offset, tif, repr=None, etf_flags=0) -> bool Change type of the frame member

  @param pfn: (C++: const func_t ) pointer to function @param offset: (C++: uval_t) member offset in the frame structure, in bytes @param tif: (C++: const tinfo_t &) variable type @param repr: (C++: const struct value_repr_t ) variable representation @param etf_flags: (C++: uint) @see: type changing flags @return: success

`def set_frame_size(pfn: func_t *, frsize: asize_t, frregs: ushort, argsize: asize_t)`

  set_frame_size(pfn, frsize, frregs, argsize) -> bool Set size of function frame. Note: The returned size may not include all stack arguments. It does so only for __stdcall and __fastcall calling conventions. To get the entire frame size for all cases use frame.get_func_frame(pfn).get_size()

  @param pfn: (C++: func_t *) pointer to function structure @param frsize: (C++: asize_t) size of function local variables @param frregs: (C++: ushort) size of saved registers @param argsize: (C++: asize_t) size of function arguments that will be purged from the stack upon return @return: success

`def set_purged(ea: ea_t, nbytes: int, override_old_value: bool)`

  set_purged(ea, nbytes, override_old_value) -> bool Set the number of purged bytes for a function or data item (funcptr). This function will update the database and plan to reanalyze items referencing the specified address. It works only for processors with PR_PURGING bit in 16 and 32 bit modes.

  @param ea: (C++: ea_t) address of the function of item @param nbytes: (C++: int) number of purged bytes @param override_old_value: (C++: bool) may overwrite old information about purged bytes @return: success

`def set_regvar_cmt(pfn: func_t *, v: regvar_t, cmt: char const *)`

  set_regvar_cmt(pfn, v, cmt) -> int Set comment for a register variable.

  @param pfn: (C++: func_t ) function in question @param v: (C++: regvar_t ) variable to rename @param cmt: (C++: const char *) new comment @return: Register variable error codes

`def soff_to_fpoff(pfn: func_t *, soff: uval_t)`

  soff_to_fpoff(pfn, soff) -> sval_t Convert struct offsets into fp-relative offsets. This function converts the offsets inside the udt_type_data_t object into the frame pointer offsets (for example, EBP-relative).

  @param pfn: (C++: func_t *) @param soff: (C++: uval_t)

`def update_fpd(pfn: func_t *, fpd: asize_t)`

  update_fpd(pfn, fpd) -> bool Update frame pointer delta.

  @param pfn: (C++: func_t *) pointer to function structure @param fpd: (C++: asize_t) new fpd value. cannot be bigger than the local variable range size. @return: success

## Classes

`class regvar_t (*args)`

  Proxy of C++ regvar_t class.

  init(self) -> regvar_t init(self, r) -> regvar_t

  @param r: regvar_t const &

  ### Ancestors

  - range_t

  ### Instance variables

  `var canon : char *`

    canonical register name (case-insensitive)

  `var cmt : char *`

    comment to appear near definition

  `var user : char *`

    user-defined register name

  ### Methods

  `def swap(self, r: regvar_t)`

    swap(self, r)

    @param r: regvar_t &

  ### Inherited members

  - `range_t`:
    - `clear`
    - `compare`
    - `contains`
    - `empty`
    - `end_ea`
    - `extend`
    - `intersect`
    - `overlaps`
    - `size`
    - `start_ea`
    - `thisown`
`class stkpnt_t`

  Proxy of C++ stkpnt_t class.

  init(self) -> stkpnt_t

  ### Instance variables

  `var ea : ea_t`

    ea

  `var spd : sval_t`

    spd

  `var thisown`

    The membership flag

  ### Methods

  `def compare(self, r: stkpnt_t) ‑> int`

    compare(self, r) -> int

    @param r: stkpnt_t const &

`class stkpnts_t`

  Proxy of C++ stkpnts_t class.

  init(self) -> stkpnts_t

  ### Instance variables

  `var thisown`

    The membership flag

  ### Methods

  `def compare(self, r: stkpnts_t) ‑> int`

    compare(self, r) -> int

    @param r: stkpnts_t const &

`class xreflist_entry_t`

  Proxy of C++ xreflist_entry_t class.

  init(self) -> xreflist_entry_t

  ### Instance variables

  `var ea : ea_t`

    Location of the insn referencing the stack frame member.

  `var opnum : uchar`

    Number of the operand of that instruction.

  `var thisown`

    The membership flag

  `var type : uchar`

    The type of xref (cref_t & dref_t)

  ### Methods

  `def compare(self, r: xreflist_entry_t) ‑> int`

    compare(self, r) -> int

    @param r: xreflist_entry_t const &

`class xreflist_t (*args)`

  Proxy of C++ qvector< xreflist_entry_t > class.

  init(self) -> xreflist_t init(self, x) -> xreflist_t

  @param x: qvector< xreflist_entry_t > const &

  ### Instance variables

  `var thisown`

    The membership flag

  ### Methods

  `def add_unique(self, x: xreflist_entry_t) ‑> bool`

    add_unique(self, x) -> bool

    @param x: xreflist_entry_t const &

  `def at(self, _idx: size_t)`

    at(self, _idx) -> xreflist_entry_t

    @param _idx: size_t

  `def back(self)`
  `def begin(self, *args)`

    begin(self) -> xreflist_entry_t

  `def capacity(self)`

    capacity(self) -> size_t

  `def clear(self)`

    clear(self)

  `def empty(self) ‑> bool`

    empty(self) -> bool

  `def end(self, *args)`

    end(self) -> xreflist_entry_t

  `def erase(self, *args)`

    erase(self, it) -> xreflist_entry_t

    @param it: qvector< xreflist_entry_t >::iterator

    erase(self, first, last) -> xreflist_entry_t

    @param first: qvector< xreflist_entry_t >::iterator @param last: qvector< xreflist_entry_t >::iterator

  `def extract(self)`

    extract(self) -> xreflist_entry_t

  `def find(self, *args)`

    find(self, x) -> xreflist_entry_t

    @param x: xreflist_entry_t const &

  `def front(self)`
  `def grow(self, *args)`

    grow(self, x=xreflist_entry_t())

    @param x: xreflist_entry_t const &

  `def has(self, x: xreflist_entry_t) ‑> bool`

    has(self, x) -> bool

    @param x: xreflist_entry_t const &

  `def inject(self, s: xreflist_entry_t, len: size_t)`

    inject(self, s, len)

    @param s: xreflist_entry_t * @param len: size_t

  `def insert(self, it: xreflist_entry_t, x: xreflist_entry_t)`

    insert(self, it, x) -> xreflist_entry_t

    @param it: qvector< xreflist_entry_t >::iterator @param x: xreflist_entry_t const &

  `def pop_back(self)`

    pop_back(self)

  `def push_back(self, *args)`

    push_back(self, x)

    @param x: xreflist_entry_t const &

    push_back(self) -> xreflist_entry_t

  `def qclear(self)`

    qclear(self)

  `def reserve(self, cnt: size_t)`

    reserve(self, cnt)

    @param cnt: size_t

  `def resize(self, *args)`

    resize(self, _newsize, x)

    @param _newsize: size_t @param x: xreflist_entry_t const &

    resize(self, _newsize)

    @param _newsize: size_t

  `def size(self)`

    size(self) -> size_t

  `def swap(self, r: xreflist_t)`

    swap(self, r)

    @param r: qvector< xreflist_entry_t > &

  `def truncate(self)`

    truncate(self)