| name | ida-domain-api |
| description | Analyze binaries using the Domain API for IDA Pro. Use when examining program structure, functions, disassembly, cross-references, or strings. |
Domain API for IDA Pro
Use this skill to efficiently use the Domain API for IDA Pro, which is easier and more concise than the legacy IDA Python SDK.
Always prefer the IDA Domain API over the legacy low-level IDA Python SDK. The Domain API provides a clean, Pythonic interface that is easier to use and understand.
Documentation Resources
Available API modules: bytes, comments, database, entries, flowchart, functions, heads, hooks, instructions, names, operands, segments, signature_files, strings, types, xrefs
To fetch specific API documentation, use URLs like:
https://ida-domain.docs.hex-rays.com/ref/functions/index.md - Function analysis API
https://ida-domain.docs.hex-rays.com/ref/xrefs/index.md - Cross-reference API
https://ida-domain.docs.hex-rays.com/ref/strings/index.md - String analysis API
Opening a Database
from ida_domain import Database
from ida_domain.database import IdaCommandOptions
ida_options = IdaCommandOptions(auto_analysis=True, new_database=False)
with Database.open("path/to/binary", ida_options, save_on_close=True) as db:
pass
Key Database Properties
with Database.open(path, ida_options) as db:
db.minimum_ea
db.maximum_ea
db.metadata
db.architecture
db.functions
db.strings
db.segments
db.names
db.entries
db.types
db.comments
db.xrefs
db.bytes
db.instructions
Functions
Iterating Functions
for func in db.functions:
print(db.functions.get_name(func))
count = len(db.functions)
Finding Functions
func = db.functions.get_at(0x401000)
func = db.functions.get_function_by_name("main")
func = db.functions.get_next(ea)
for func in db.functions.get_between(start_ea, end_ea):
print(func.start_ea)
Function Properties
name = db.functions.get_name(func)
signature = db.functions.get_signature(func)
flags = db.functions.get_flags(func)
db.functions.is_far(func)
db.functions.does_return(func)
Function Code
lines = db.functions.get_disassembly(func, remove_tags=True)
pseudocode = db.functions.get_pseudocode(func, remove_tags=True)
microcode = db.functions.get_microcode(func, remove_tags=True)
Function Analysis
for insn in db.functions.get_instructions(func):
print(insn.ea)
flowchart = db.functions.get_flowchart(func)
for block in flowchart:
print(f"Block: {block.start_ea:#x} - {block.end_ea:#x}")
callers = db.functions.get_callers(func)
callees = db.functions.get_callees(func)
for chunk in db.functions.get_chunks(func):
print(f"Chunk: {chunk.start_ea:#x}, main={chunk.is_main}")
for data_ea in db.functions.get_data_items(func):
print(f"Data at {data_ea:#x}")
Local Variables
lvars = db.functions.get_local_variables(func)
for lvar in lvars:
print(f"{lvar.name}: {lvar.type_str}, arg={lvar.is_argument}")
lvar = db.functions.get_local_variable_by_name(func, "result")
refs = db.functions.get_local_variable_references(func, lvar)
for ref in refs:
print(f"Line {ref.line_number}: {ref.access_type} in {ref.context}")
Modifying Functions
db.functions.set_name(func, "new_name")
db.functions.set_comment(func, "This function does X", repeatable=False)
db.functions.create(ea)
db.functions.remove(ea)
Instructions
Iterating Instructions
for insn in db.instructions:
print(db.instructions.get_disassembly(insn))
for insn in db.instructions.get_between(start_ea, end_ea):
print(insn.ea)
Getting Instructions
insn = db.instructions.get_at(ea)
insn = db.instructions.get_previous(ea)
Instruction Properties
disasm = db.instructions.get_disassembly(insn)
mnemonic = db.instructions.get_mnemonic(insn)
db.instructions.is_valid(insn)
Control Flow Analysis
db.instructions.is_call_instruction(insn)
db.instructions.is_indirect_jump_or_call(insn)
db.instructions.breaks_sequential_flow(insn)
Working with Operands
count = db.instructions.get_operands_count(insn)
operands = db.instructions.get_operands(insn)
for op in operands:
info = op.get_info()
print(f"Operand {op.number}: {op.type.name}")
if isinstance(op, RegisterOperand):
print(f" Register: {op.get_register_name()}")
elif isinstance(op, ImmediateOperand):
print(f" Value: 0x{op.get_value():x}")
elif isinstance(op, MemoryOperand):
if op.is_direct_memory():
print(f" Memory: 0x{op.get_address():x}")
Segments
Iterating Segments
for segment in db.segments:
name = db.segments.get_name(segment)
size = db.segments.get_size(segment)
print(f"{name}: {segment.start_ea:#x} - {segment.end_ea:#x}")
count = len(db.segments)
Finding Segments
seg = db.segments.get_at(0x401000)
seg = db.segments.get_by_name(".text")
Segment Properties
name = db.segments.get_name(segment)
size = db.segments.get_size(segment)
bitness = db.segments.get_bitness(segment)
seg_class = db.segments.get_class(segment)
Creating Segments
from ida_domain.segments import PredefinedClass, AddSegmentFlags
seg = db.segments.add(
seg_para=0,
start_ea=0x1000,
end_ea=0x2000,
seg_name="MySegment",
seg_class=PredefinedClass.CODE
)
seg = db.segments.append(seg_para=0, seg_size=0x1000, seg_name="NewSeg")
Modifying Segments
from ida_domain.segments import SegmentPermissions, AddressingMode
db.segments.set_name(segment, "new_name")
db.segments.set_permissions(segment, SegmentPermissions.READ | SegmentPermissions.EXEC)
db.segments.add_permissions(segment, SegmentPermissions.WRITE)
db.segments.remove_permissions(segment, SegmentPermissions.WRITE)
db.segments.set_addressing_mode(segment, AddressingMode.BIT64)
db.segments.set_comment(segment, "Code section", repeatable=False)
Strings
Iterating Strings
for string in db.strings:
print(f"{string.address:#x}: {string}")
first_string = db.strings[0]
count = len(db.strings)
Finding Strings
string = db.strings.get_at(0x402000)
for s in db.strings.get_between(start_ea, end_ea):
print(s.contents)
String Properties
print(string.address)
print(string.length)
print(string.type)
print(string.encoding)
print(string.contents)
print(str(string))
Rebuilding String List
from ida_domain.strings import StringListConfig, StringType
config = StringListConfig(
string_types=[StringType.C, StringType.C_16],
min_len=3,
only_ascii_7bit=False
)
db.strings.rebuild(config)
db.strings.clear()
Xrefs
Getting References TO an Address
for xref in db.xrefs.to_ea(target_ea):
print(f"{xref.from_ea:#x} -> {xref.to_ea:#x} ({xref.type.name})")
for ea in db.xrefs.code_refs_to_ea(target_ea, flow=False):
print(f"Code ref from {ea:#x}")
for ea in db.xrefs.data_refs_to_ea(target_ea):
print(f"Data ref from {ea:#x}")
for ea in db.xrefs.calls_to_ea(func_ea):
print(f"Called from {ea:#x}")
for caller in db.xrefs.get_callers(func_ea):
print(f"Called from {caller.name} at {caller.ea:#x}")
Getting References FROM an Address
for xref in db.xrefs.from_ea(source_ea):
print(f"{xref.from_ea:#x} -> {xref.to_ea:#x}")
for ea in db.xrefs.code_refs_from_ea(source_ea):
print(f"Code ref to {ea:#x}")
for ea in db.xrefs.calls_from_ea(source_ea):
print(f"Calls {ea:#x}")
Data Access Analysis
for ea in db.xrefs.reads_of_ea(data_ea):
print(f"Read by {ea:#x}")
for ea in db.xrefs.writes_to_ea(data_ea):
print(f"Written by {ea:#x}")
XrefInfo Properties
xref.is_call
xref.is_jump
xref.is_read
xref.is_write
xref.is_flow
xref.user
Names
Iterating Names
for ea, name in db.names:
print(f"{ea:#x}: {name}")
count = len(db.names)
Getting Names
name = db.names.get_at(0x401000)
ea, name = db.names[0]
Setting Names
from ida_domain.names import SetNameFlags
db.names.set_name(ea, "my_function")
db.names.set_name(ea, "my_func", flags=SetNameFlags.CHECK)
db.names.force_name(ea, "func")
db.names.delete(ea)
Name Properties
db.names.is_valid_name("my_name")
db.names.is_public_name(ea)
db.names.is_weak_name(ea)
db.names.make_name_public(ea)
db.names.make_name_non_public(ea)
db.names.make_name_weak(ea)
db.names.make_name_non_weak(ea)
Demangling
from ida_domain.names import DemangleFlags
demangled = db.names.get_demangled_name(ea)
demangled = db.names.get_demangled_name(ea, DemangleFlags.NORETTYPE)
demangled = db.names.demangle_name("?main@@YAXXZ")
Types
Getting Types
tinfo = db.types.get_by_name("MyStruct")
tinfo = db.types.get_at(ea)
for tinfo in db.types:
print(tinfo)
Parsing Types
errors = db.types.parse_declarations(None, "struct Point { int x; int y; };")
tinfo = db.types.parse_one_declaration(None, "int (*callback)(void*)", "callback_t")
errors = db.types.parse_header_file(library, Path("header.h"))
Applying Types
from ida_domain.types import TypeApplyFlags
db.types.apply_at(tinfo, ea, flags=TypeApplyFlags.DEFINITE)
Type Details
details = db.types.get_details(tinfo)
print(details.name)
print(details.size)
print(details.attributes)
if details.udt:
print(details.udt.num_members)
print(details.udt.attributes)
if details.func:
print(details.func.attributes)
Type Libraries
lib = db.types.load_library(Path("types.til"))
lib = db.types.create_library(Path("new.til"), "My Types")
db.types.import_type(source_lib, "MyStruct")
db.types.export_type(dest_lib, "MyStruct")
db.types.save_library(lib, Path("output.til"))
db.types.unload_library(lib)
Bytes
Reading Values
byte = db.bytes.get_byte_at(ea)
word = db.bytes.get_word_at(ea)
dword = db.bytes.get_dword_at(ea)
qword = db.bytes.get_qword_at(ea)
float_val = db.bytes.get_float_at(ea)
double_val = db.bytes.get_double_at(ea)
data = db.bytes.get_bytes_at(ea, size=16)
original = db.bytes.get_original_bytes_at(ea, size=16)
string = db.bytes.get_string_at(ea)
cstring = db.bytes.get_cstring_at(ea, max_length=256)
Writing Values
db.bytes.set_byte_at(ea, 0x90)
db.bytes.set_word_at(ea, 0x1234)
db.bytes.set_dword_at(ea, 0x12345678)
db.bytes.set_qword_at(ea, 0x123456789ABCDEF0)
db.bytes.set_bytes_at(ea, b"\x90\x90\x90")
Patching (with History)
db.bytes.patch_byte_at(ea, 0x90)
db.bytes.patch_bytes_at(ea, data)
db.bytes.revert_byte_at(ea)
orig = db.bytes.get_original_byte_at(ea)
Searching
from ida_domain.bytes import SearchFlags
ea = db.bytes.find_bytes_between(b"\x55\x89\xe5", start_ea, end_ea)
addresses = db.bytes.find_binary_sequence(b"\x90\x90")
ea = db.bytes.find_text_between("error", flags=SearchFlags.DOWN)
ea = db.bytes.find_immediate_between(0x1234)
Creating Data Items
from ida_domain.strings import StringType
db.bytes.create_byte_at(ea, count=4)
db.bytes.create_word_at(ea)
db.bytes.create_dword_at(ea, count=10)
db.bytes.create_qword_at(ea)
db.bytes.create_float_at(ea)
db.bytes.create_double_at(ea)
db.bytes.create_string_at(ea, string_type=StringType.C)
db.bytes.create_struct_at(ea, count=1, tid=struct_tid)
Querying Properties
size = db.bytes.get_data_size_at(ea)
db.bytes.is_value_initialized_at(ea)
db.bytes.is_code_at(ea)
db.bytes.is_data_at(ea)
db.bytes.is_head_at(ea)
db.bytes.is_tail_at(ea)
db.bytes.is_unknown_at(ea)
disasm = db.bytes.get_disassembly_at(ea)
Navigation
next_head = db.bytes.get_next_head(ea)
prev_head = db.bytes.get_previous_head(ea)
next_addr = db.bytes.get_next_address(ea)
prev_addr = db.bytes.get_previous_address(ea)
Comments
Regular Comments
from ida_domain.comments import CommentKind
info = db.comments.get_at(ea, CommentKind.REGULAR)
if info:
print(info.comment)
db.comments.set_at(ea, "This is important", CommentKind.REGULAR)
db.comments.set_at(ea, "Shows everywhere", CommentKind.REPEATABLE)
db.comments.delete_at(ea, CommentKind.ALL)
Iterating Comments
for comment_info in db.comments:
print(f"{comment_info.ea:#x}: {comment_info.comment}")
for info in db.comments.get_all(CommentKind.ALL):
print(f"{info.ea:#x} (repeatable={info.repeatable}): {info.comment}")
Extra Comments (Anterior/Posterior)
from ida_domain.comments import ExtraCommentKind
db.comments.set_extra_at(ea, index=0, comment="Before line", kind=ExtraCommentKind.ANTERIOR)
db.comments.set_extra_at(ea, index=0, comment="After line", kind=ExtraCommentKind.POSTERIOR)
comment = db.comments.get_extra_at(ea, index=0, kind=ExtraCommentKind.ANTERIOR)
for comment in db.comments.get_all_extra_at(ea, ExtraCommentKind.ANTERIOR):
print(comment)
db.comments.delete_extra_at(ea, index=0, kind=ExtraCommentKind.ANTERIOR)
Entries
Iterating Entry Points
for entry in db.entries:
print(f"{entry.ordinal}: {entry.name} at {entry.address:#x}")
count = len(db.entries)
first = db.entries[0]
Finding Entries
entry = db.entries.get_at(ea)
entry = db.entries.get_by_ordinal(1)
entry = db.entries.get_by_name("main")
entry = db.entries.get_at_index(0)
Entry Properties
print(entry.ordinal)
print(entry.address)
print(entry.name)
print(entry.forwarder_name)
entry.has_forwarder()
Modifying Entries
db.entries.add(address=ea, name="new_entry", ordinal=10)
db.entries.rename(ordinal=10, new_name="renamed_entry")
db.entries.set_forwarder(ordinal=10, forwarder_name="other.dll!func")
db.entries.exists(ordinal=10)
Utility Iterators
for ordinal in db.entries.get_ordinals():
print(ordinal)
for addr in db.entries.get_addresses():
print(f"{addr:#x}")
for name in db.entries.get_names():
print(name)
for fwd in db.entries.get_forwarders():
print(f"{fwd.ordinal}: {fwd.name}")
Heads
Iterating Heads
for ea in db.heads:
print(f"Head at {ea:#x}")
for ea in db.heads.get_between(start_ea, end_ea):
print(ea)
Navigation
next_ea = db.heads.get_next(ea)
prev_ea = db.heads.get_previous(ea)
Head Properties
db.heads.is_head(ea)
db.heads.is_tail(ea)
db.heads.is_code(ea)
db.heads.is_data(ea)
db.heads.is_unknown(ea)
size = db.heads.size(ea)
start, end = db.heads.bounds(ea)
Flowchart
Creating Flowcharts
from ida_domain.flowchart import FlowChart, FlowChartFlags
flowchart = FlowChart(db, func=my_func)
flowchart = FlowChart(db, bounds=(start_ea, end_ea))
flowchart = FlowChart(db, func=my_func, flags=FlowChartFlags.PREDS)
Iterating Basic Blocks
for block in flowchart:
print(f"Block {block.id}: {block.start_ea:#x} - {block.end_ea:#x}")
block = flowchart[0]
count = len(flowchart)
Block Navigation
for succ in block.get_successors():
print(f"Successor: {succ.id}")
for pred in block.get_predecessors():
print(f"Predecessor: {pred.id}")
succ_count = block.count_successors()
pred_count = block.count_predecessors()
Block Instructions
for insn in block.get_instructions():
print(f"{insn.ea:#x}")
Enums Reference
XrefType
from ida_domain.xrefs import XrefType
XrefType.OFFSET
XrefType.WRITE
XrefType.READ
XrefType.CALL_FAR
XrefType.CALL_NEAR
XrefType.JUMP_FAR
XrefType.JUMP_NEAR
XrefType.ORDINARY_FLOW
xref_type.is_code_ref()
xref_type.is_data_ref()
FunctionFlags
from ida_domain.functions import FunctionFlags
FunctionFlags.NORET
FunctionFlags.LIB
FunctionFlags.THUNK
FunctionFlags.HIDDEN
FunctionFlags.LUMINA
FunctionFlags.FAR
FunctionFlags.FRAME
LocalVariableAccessType
from ida_domain.functions import LocalVariableAccessType
LocalVariableAccessType.READ
LocalVariableAccessType.WRITE
LocalVariableAccessType.ADDRESS
LocalVariableContext
from ida_domain.functions import LocalVariableContext
LocalVariableContext.ASSIGNMENT
LocalVariableContext.CONDITION
LocalVariableContext.CALL_ARG
LocalVariableContext.RETURN
LocalVariableContext.ARITHMETIC
LocalVariableContext.COMPARISON
LocalVariableContext.ARRAY_INDEX
LocalVariableContext.POINTER_DEREF
LocalVariableContext.CAST
OperandType
from ida_domain.operands import OperandType
OperandType.REGISTER
OperandType.MEMORY
OperandType.PHRASE
OperandType.DISPLACEMENT
OperandType.IMMEDIATE
OperandType.FAR_ADDRESS
OperandType.NEAR_ADDRESS
StringType
from ida_domain.strings import StringType
StringType.C
StringType.C_16
StringType.C_32
StringType.PASCAL
StringType.LEN2
StringType.LEN4
SegmentPermissions
from ida_domain.segments import SegmentPermissions
SegmentPermissions.READ
SegmentPermissions.WRITE
SegmentPermissions.EXEC
SegmentPermissions.ALL
AddressingMode
from ida_domain.segments import AddressingMode
AddressingMode.BIT16
AddressingMode.BIT32
AddressingMode.BIT64
PredefinedClass
from ida_domain.segments import PredefinedClass
PredefinedClass.CODE
PredefinedClass.DATA
PredefinedClass.CONST
PredefinedClass.STACK
PredefinedClass.BSS
PredefinedClass.XTRN
CommentKind
from ida_domain.comments import CommentKind
CommentKind.REGULAR
CommentKind.REPEATABLE
CommentKind.ALL
ExtraCommentKind
from ida_domain.comments import ExtraCommentKind
ExtraCommentKind.ANTERIOR
ExtraCommentKind.POSTERIOR
TypeAttr
from ida_domain.types import TypeAttr
TypeAttr.INT, TypeAttr.UINT
TypeAttr.FLOAT, TypeAttr.DOUBLE
TypeAttr.PTR, TypeAttr.ARRAY
TypeAttr.FUNC, TypeAttr.STRUCT
TypeAttr.UNION, TypeAttr.ENUM
TypeAttr.CONST, TypeAttr.VOLATILE
FlowChartFlags
from ida_domain.flowchart import FlowChartFlags
FlowChartFlags.NONE
FlowChartFlags.NOEXT
FlowChartFlags.PREDS
Common Patterns
Find All Calls to a Function
func = db.functions.get_function_by_name("malloc")
if func:
for caller in db.xrefs.get_callers(func.start_ea):
print(f"Called from {caller.name} at {caller.ea:#x}")
Rename Functions Based on Strings
for func in db.functions:
for insn in db.functions.get_instructions(func):
for xref in db.xrefs.from_ea(insn.ea):
string = db.strings.get_at(xref.to_ea)
if string and "error" in str(string).lower():
db.functions.set_name(func, f"func_with_error_{func.start_ea:x}")
break
Analyze Function Complexity
func = db.functions.get_at(ea)
flowchart = db.functions.get_flowchart(func)
print(f"Basic blocks: {len(flowchart)}")
total_edges = sum(block.count_successors() for block in flowchart)
print(f"Cyclomatic complexity: {total_edges - len(flowchart) + 2}")
Export Function Pseudocode
for func in db.functions:
name = db.functions.get_name(func)
try:
pseudocode = db.functions.get_pseudocode(func)
print(f"// {name}")
for line in pseudocode:
print(line)
except RuntimeError:
print(f"// Could not decompile {name}")
Find Cross-References to Strings
for string in db.strings:
refs = list(db.xrefs.to_ea(string.address))
if refs:
print(f'"{string}" referenced from:')
for xref in refs:
print(f" {xref.from_ea:#x}")
Legacy API (Avoid)
The legacy idc, idautils, ida_funcs APIs still work but are harder to use. Prefer the Domain API for new analysis scripts. Only use legacy APIs when Domain API doesn't expose needed functionality.