255 lines
8.4 KiB
C++
255 lines
8.4 KiB
C++
/*
|
|
* Interactive disassembler (IDA).
|
|
* Copyright (c) 1990-2021 Hex-Rays
|
|
* ALL RIGHTS RESERVED.
|
|
*
|
|
*/
|
|
|
|
#ifndef _OFFSET_HPP
|
|
#define _OFFSET_HPP
|
|
|
|
#include <nalt.hpp>
|
|
#include <segment.hpp>
|
|
|
|
/*! \file offset.hpp
|
|
|
|
\brief Functions that deal with offsets.
|
|
|
|
"Being an offset" is a characteristic of an operand.
|
|
This means that operand or its part represent offset from
|
|
some address in the program. This linear address is called
|
|
"offset base". Some operands may have 2 offsets simultaneously.
|
|
Generally, IDA doesn't handle this except for Motorola outer offsets.
|
|
Thus there may be two offset values in an operand: simple offset and
|
|
outer offset.
|
|
|
|
Outer offsets are handled by specifying special operand number:
|
|
it should be ORed with #OPND_OUTER value.
|
|
|
|
See bytes.hpp for further explanation of operand numbers.
|
|
*/
|
|
|
|
|
|
/// Get default reference type depending on the segment.
|
|
/// \return one of ::REF_OFF8,::REF_OFF16,::REF_OFF32
|
|
|
|
idaman reftype_t ida_export get_default_reftype(ea_t ea);
|
|
|
|
|
|
/// Convert operand to a reference.
|
|
/// To delete an offset, use clr_op_type() function.
|
|
/// \param ea linear address.
|
|
/// if 'ea' has unexplored bytes, try to convert them to
|
|
/// - no segment: fail
|
|
/// - 16bit segment: to 16bit word data
|
|
/// - 32bit segment: to dword
|
|
/// \param n number of operand (may be ORed with #OPND_OUTER)
|
|
/// - 0: first
|
|
/// - 1: second
|
|
/// - 2: third
|
|
/// - #OPND_MASK: all operands
|
|
/// \param ri reference information
|
|
/// \return success
|
|
|
|
idaman bool ida_export op_offset_ex(ea_t ea, int n, const refinfo_t *ri);
|
|
|
|
|
|
/// See op_offset_ex()
|
|
|
|
idaman bool ida_export op_offset(
|
|
ea_t ea,
|
|
int n,
|
|
uint32 type_and_flags,
|
|
ea_t target=BADADDR,
|
|
ea_t base=0,
|
|
adiff_t tdelta=0);
|
|
|
|
|
|
/// Convert operand to a reference with the default reference type
|
|
|
|
inline bool op_plain_offset(ea_t ea, int n, ea_t base)
|
|
{
|
|
reftype_t reftype = get_default_reftype(ea);
|
|
return op_offset(ea, n, reftype, BADADDR, base) != 0;
|
|
}
|
|
|
|
|
|
/// Get offset base value
|
|
/// \param ea linear address
|
|
/// \param n number of operand
|
|
/// \return offset base or #BADADDR
|
|
|
|
inline ea_t get_offbase(ea_t ea, int n)
|
|
{
|
|
refinfo_t ri;
|
|
if ( !get_refinfo(&ri, ea, n) )
|
|
return BADADDR;
|
|
return ri.base;
|
|
}
|
|
|
|
|
|
/// Get offset expression (in the form "offset name+displ").
|
|
/// This function uses offset translation function (\ph{translate}) if your IDP
|
|
/// module has such a function. Translation function is used to map linear
|
|
/// addresses in the program (only for offsets).
|
|
///
|
|
/// Example: suppose we have instruction at linear address 0x00011000:
|
|
/// \v{mov ax, [bx+7422h]}
|
|
/// and at ds:7422h:
|
|
/// \v{array dw ...}
|
|
/// We want to represent the second operand with an offset expression, so
|
|
/// then we call:
|
|
/// \v{
|
|
/// get_offset_expresion(0x001100, 1, 0x001102, 0x7422, buf);
|
|
/// | | | | |
|
|
/// | | | | +output buffer
|
|
/// | | | +value of offset expression
|
|
/// | | +address offset value in the instruction
|
|
/// | +the second operand
|
|
/// +address of instruction
|
|
/// }
|
|
/// and the function will return a colored string:
|
|
/// \v{offset array}
|
|
/// \param buf output buffer to hold offset expression
|
|
/// \param ea start of instruction or data with the offset expression
|
|
/// \param n number of operand (may be ORed with #OPND_OUTER)
|
|
/// - 0: first operand
|
|
/// - 1: second operand
|
|
/// \param from linear address of instruction operand or data referring to
|
|
/// the name. This address will be used to get fixup information,
|
|
/// so it should point to exact position of operand in the
|
|
/// instruction.
|
|
/// \param offset value of operand or its part. The function will return
|
|
/// text representation of this value as offset expression.
|
|
/// \param getn_flags combination of:
|
|
/// - #GETN_APPZERO: meaningful only if the name refers to
|
|
/// a structure. appends the struct field name
|
|
/// if the field offset is zero
|
|
/// - #GETN_NODUMMY: do not generate dummy names for the expression
|
|
/// but pretend they already exist
|
|
/// (useful to verify that the offset expression
|
|
/// can be represented)
|
|
/// \retval 0 can't convert to offset expression
|
|
/// \retval 1 ok, a simple offset expression
|
|
/// \retval 2 ok, a complex offset expression
|
|
|
|
|
|
idaman int ida_export get_offset_expression(
|
|
qstring *buf,
|
|
ea_t ea,
|
|
int n,
|
|
ea_t from,
|
|
adiff_t offset,
|
|
int getn_flags=0);
|
|
|
|
|
|
/// See get_offset_expression()
|
|
|
|
idaman int ida_export get_offset_expr(
|
|
qstring *buf,
|
|
ea_t ea,
|
|
int n,
|
|
const refinfo_t &ri,
|
|
ea_t from,
|
|
adiff_t offset,
|
|
int getn_flags=0);
|
|
|
|
|
|
/// Does the specified address contain a valid OFF32 value?.
|
|
/// For symbols in special segments the displacement is not taken into account.
|
|
/// If yes, then the target address of OFF32 will be returned.
|
|
/// If not, then #BADADDR is returned.
|
|
|
|
idaman ea_t ida_export can_be_off32(ea_t ea);
|
|
|
|
|
|
/// Try to calculate the offset base
|
|
/// This function takes into account the fixup information,
|
|
/// current ds and cs values.
|
|
/// \param ea the referencing instruction/data address
|
|
/// \param n operand number
|
|
/// - 0: first operand
|
|
/// - 1: other operand
|
|
/// \return output base address or #BADADDR
|
|
|
|
idaman ea_t ida_export calc_offset_base(ea_t ea, int n);
|
|
|
|
|
|
/// Try to calculate the offset base.
|
|
/// 2 bases are checked: current ds and cs.
|
|
/// If fails, return #BADADDR
|
|
|
|
idaman ea_t ida_export calc_probable_base_by_value(ea_t ea, uval_t off);
|
|
|
|
|
|
/// Calculate the target and base addresses of an offset expression.
|
|
/// The calculated target and base addresses are returned in the locations
|
|
/// pointed by 'base' and 'target'. In case 'ri.base' is #BADADDR, the
|
|
/// function calculates the offset base address from the referencing
|
|
/// instruction/data address.
|
|
/// The target address is copied from ri.target. If ri.target is #BADADDR
|
|
/// then the target is calculated using the base address and 'opval'.
|
|
/// This function also checks if 'opval' matches the full value of the
|
|
/// reference and takes in account the memory-mapping.
|
|
/// \param target output target address
|
|
/// \param base output base address
|
|
/// \param from the referencing instruction/data address
|
|
/// \param ri reference info block from the database
|
|
/// \param opval operand value (usually op_t::value or op_t::addr)
|
|
/// \return success
|
|
idaman bool ida_export calc_reference_data(
|
|
ea_t *target,
|
|
ea_t *base,
|
|
ea_t from,
|
|
const refinfo_t &ri,
|
|
adiff_t opval);
|
|
|
|
|
|
/// Add xrefs for a reference from the given instruction (\insn_t{ea}).
|
|
/// This function creates a cross references to the target and the base.
|
|
/// insn_t::add_off_drefs() calls this function to create xrefs for
|
|
/// 'offset' operand.
|
|
/// \param insn the referencing instruction
|
|
/// \param from the referencing instruction/data address
|
|
/// \param ri reference info block from the database
|
|
/// \param opval operand value (usually op_t::value or op_t::addr)
|
|
/// \param type type of xref
|
|
/// \param opoff offset of the operand from the start of instruction
|
|
/// \return the target address of the reference
|
|
idaman ea_t ida_export add_refinfo_dref(
|
|
const insn_t &insn,
|
|
ea_t from,
|
|
const refinfo_t &ri,
|
|
adiff_t opval,
|
|
dref_t type,
|
|
int opoff);
|
|
|
|
|
|
/// Calculates the target, using the provided refinfo_t
|
|
|
|
inline ea_t calc_target(ea_t from, adiff_t opval, const refinfo_t &ri)
|
|
{
|
|
ea_t target;
|
|
if ( !calc_reference_data(&target, NULL, from, ri, opval) )
|
|
return BADADDR;
|
|
return target;
|
|
}
|
|
|
|
/// Retrieves refinfo_t structure and calculates the target
|
|
|
|
inline ea_t calc_target(ea_t from, ea_t ea, int n, adiff_t opval)
|
|
{
|
|
refinfo_t ri;
|
|
return get_refinfo(&ri, ea, n) ? calc_target(from, opval, ri) : BADADDR;
|
|
}
|
|
|
|
/// Calculate the value of the reference base.
|
|
|
|
inline ea_t calc_basevalue(ea_t target, ea_t base)
|
|
{
|
|
return base - get_segm_base(getseg(target));
|
|
}
|
|
|
|
|
|
#endif // _OFFSET_HPP
|