Skip to main content

IDA Colors

CI

Parser for color tags in IDA.

Usage

$ uv run ida-colors <path-to-idb>
...
    "LDR             X8, [X19,#0x10]"
        Insn("LDR")
        Opnd1(Reg("X8"))
        Opnd2(Symbol("["), Reg("X19"), Symbol(",#"), Number("0x10"), Symbol("]"))
...

Numbers

numbers() returns the integers of a parsed line, with the - printed in front of each one applied:

>>> from ida_colors import numbers, parse_full
>>> numbers(parse_full(ida_lines.generate_disasm_line(ea, 0)))  # STP XZR, XZR, [X1,#-0xD8]
[Number(value=-216, operand=3, standalone=False)]

standalone is true when the number is the entire operand, give or take a #, = or -: #0x10, -1 and =0xCBF29CE4 are, while [X1,#0x10] and [rsp+28h+var_20] are not.

u8() to u64() and i8() to i64() reinterpret the value at a width, so -1 and 0xFFFFFFFF compare equal as u32(), and return None when it doesn't fit. Spellings other than plain decimal, 0x10 and 10h (floats, chars, other radixes) are skipped rather than guessed. Void operands, immediates that IDA colors differently because they fall inside the database's address range, count as numbers too, so the result doesn't depend on the image base.

Strings

strings() returns the strings and chars that IDA shows in a line's automatic comments, as printed: quotes removed, escapes kept.

>>> from ida_colors import parse_full, strings
>>> strings(parse_full(ida_lines.generate_disasm_line(ea, 0)))  # lea rsi, aSslSession ; "SSL-Session:\n"
[String(text='SSL-Session:\\n', char=False, addr=844343, truncated=False)]

addr is where the string starts, also when IDA shows it through a pointer ("/dev/urandom" ...). truncated is true when IDA cut it short ("abi.NewName: tag too long: hw.optional."...). Chars (sub esi, 35h ; '5') have char set and no addr. Names shown the same way (; __gmon_start__) and anything else that doesn't look exactly like a string or a char are skipped.

The CLI needs IDA 9+ and the ida extra (idapro). The parser itself has no dependencies.

Development

$ uv run ruff check && uv run ruff format --check
$ uv run ty check
$ uv run pytest

tests/test_ida_constants.py checks the constants copied from IDA against a local IDA install, and is skipped when idapro can't load one. tests/test_ida_numbers.py checks parsed immediates against IDA's operand values on every .i64 in $IDA_COLORS_IDBS (opened as temporary copies), and tests/test_ida_strings.py checks parsed strings against the string literals there. Both are skipped when it's unset.

uv run python bench/bench.py times parse_full(), numbers() and strings() per line on the sample of real disassembly in tests/data/lines.json, by processor. It's not part of CI, as timings on shared runners are too noisy.

tests/test_oracle.py checks that trees, results and errors match tests/ida_colors_ref, a frozen copy of the package, on those lines and on mangled versions of them. Speedups must keep it passing. A deliberate behavior change replaces the copy with the new code.

Why?

IDA's disassembly isn't just the decoded instruction. Between decode_insn and the line you see, the processor module's printer applies a lot of heuristics and user annotations: offsets, stack variables, struct offsets, enums, chars, @PAGE/@PAGEOFF pairs, hidden implicit operands. The printed line is the only place where all of that comes together, and IDA marks it up with color tags. Parsing the tags gets you what IDA decided, without reimplementing its printer for every processor.

The textbook alternative, decode_insn and op_t.type (o_imm, o_mem, o_displ, ...), tells you what the bytes encode, not what they mean:

Instruction decode_insn says IDA prints
PowerPC addis r30, r30, (off_11FA38 - loc_1923C)@ha o_imm, value 0x10 the high half of an address difference
RISC-V auipc t2, %pcrel_hi(off_C8380) o_imm, value 0xbc a PC-relative reference to off_C8380
ARM64 ADRP X16, #qword_11FFF8@PAGE o_imm, value 0x11f000 a reference to qword_11FFF8
SPARC add %fp, arg_727, %l1 o_imm, value 0x727 the stack argument arg_727
x86-64 mov [rbp+var_30], rax o_displ, value 0xffffffffffffffd0 the stack variable var_30
x86-64 lea rdi, ds:1[rdx*2] o_mem, address 0x1 a plain number
RISC-V nop one operand, o_imm no operands
PowerPC mflr r0 two operands, the second o_idpspec0 one operand
x86-64 mul rcx two operands, implicit rax first one operand, tagged as operand 2

Metadata

Release files for ida-colors 0.0.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ida-colors 0.0.5
File Size Uploaded
ida_colors-0.0.5.tar.gz 11.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ida-colors 0.0.5
File Interpreter ABI Platform
ida_colors-0.0.5-py3-none-any.whl Python 3 none any Details

Total release size: 24.8 kB

Release files / ida_colors-0.0.5.tar.gz

Download URL ida_colors-0.0.5.tar.gz
Size 11.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e4acec20e20fd8c72e2aa0b88f4e2fa6ff20272a22bb71bf8180bead6ec9ccf2
BLAKE2b-256 checksum
How to use checksums
17d23b9abedb38cc6c769fad2ee693f18311e53467011da2fe130f8ce5df7ff6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / ida_colors-0.0.5-py3-none-any.whl

Download URL ida_colors-0.0.5-py3-none-any.whl
Size 13.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9440352c23465d37838d37aa29e140a5e2220f6f0dded2af4ea53e8c083910e1
BLAKE2b-256 checksum
How to use checksums
d6edba08b21b89bef033bc857cfd8144635d7bb3e707a9afbcd599ac9b9ba1e5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.0.5 This release

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page