Commit graph

30492 commits

Author SHA1 Message Date
Anton Kochkov
e91c636f00 test/unit: cover rz_core_graph_* per-type API entry points
The existing integration tests only reached the per-type graph
builders through the rz_core_graph() dispatcher. Add tests that call
rz_core_graph_callgraph/datarefs/coderefs/importxrefs directly and
assert they agree with the dispatcher, plus coverage for the
rz_core_graph_to_dot_str()/rz_core_graph_to_sdb_str() serializers.

Completes the work on rizinorg/rizin#992.
2026-05-29 00:22:08 +08:00
Rot127
ea146cb14d
Delete overflow test because FreeBSD times out on it. (#6412) 2026-05-28 16:03:38 +00:00
Anton Kochkov
0cdeb0df2a Add colors, Unicode and RzIL to the visual bit editor
The visual bit editor (V d 1 / V b1) ignored the active color theme,
scr.utf8 and cfg.bigendian, always showed ESIL even when RzIL was
available, overflowed the IL onto a single line, and drew the cursor
position as a detached underline. This reworks it to match the styling
of the commands users already know and adds a cursor-position summary.

- Byte order on screen follows cfg.bigendian: big-endian shows the
  byte at the current offset on the left, little-endian reorders so the
  MSB is on the left. Cursor movement and every byte-write key go
  through a MEM_BYTE() mapping so edits land on the byte under the
  cursor regardless of endianness; the buffer stays in memory order.
- chr/dec/hex byte cells are colored by value via rz_print_byte_color,
  the same helper px uses. The asm line keeps rz_asm_colorize_asm_str.
- The rzil line is colored like plf: core_colorify_il_statement is
  split into an address-prefix wrapper and a body-only colorizer
  (rz_core_il_colorize_body) shared by both. Long IL is soft-wrapped at
  the terminal width, breaking between top-level seq children and
  indenting continuations.
- RzIL is preferred over ESIL; the analysis op now also requests
  RZ_ANALYSIS_OP_MASK_IL. When neither is available the line is omitted.
- The bit under the cursor is reverse-video highlighted (a graphics
  attribute emitted regardless of scr.color); padding bits are dimmed
  via pal.comment. The empty-bit padding glyph is the middle-dot when
  color or Unicode is on, else a plain period.
- The position indicator now sits between the two bit rows as a single
  marker pointing at both, and a compact info line summarizes the
  cursor: "byte N - nibble H|L - bit B [P] - LE|BE".
- The ? help is expanded with a description of the mode and a legend
  for the position line; the key table is colored like the other
  visual help screens via rz_core_visual_append_help.
- Fix a leak of the asm op on the q/Q exit path.

Closes #6361
2026-05-28 23:14:33 +08:00
Alok Kumar Mishra
a35e896fe7
support context-aware core plugins (#6404) 2026-05-28 20:37:01 +08:00
Anton Kochkov
ef4d2334a2 arch/tms320: pdf rendering tests for c55x and c55x+ functions
Adds full-function disassembly (pdf) tests for non-trivial functions on
both CPUs, to lock in correct rendering of basic-block boundaries,
reflines (forward and backward branches), call/data/string cross-
references and operand formatting.

C55x (emulateme_nostd.ccsv5.c55x.ticoff2.dbg.coff):
  - sym._uart_write_hex: a compact two-block function with a forward
    conditional branch, an unconditional branch refline and a call ref.
  - sym.___text: a four-block loop with conditional branches both ways,
    a back-edge, a call into another function, data references and
    parallel-instruction (||) operands.

C55x+ (coff2/19_emulateme_nostd.obj):
  - sym._c_strlen: a four-block scan loop with a back-edge and forward
    and backward bcc reflines.
  - sym._main: a five-block function with nested conditional branches
    and two call references (_c_strlen, _decrypt).

All four render cleanly with the existing decoder and analyzers; no
behavior change was needed.
2026-05-28 17:44:54 +08:00
Anton Kochkov
13ebcbc2c7 arch/tms320: named instruction IDs (TMS320C55_INS_*) from the disassembler
Gives the C55x / C55x+ disassembler a Capstone-style per-instruction
identifier and threads it through to analysis, so the analyzers dispatch
on named operations instead of raw opcode bytes.

What lands
==========

* librz/arch/isa/tms320/tms320c55x_insn.{c,h} -- a shared TMS320C55InsID enum
  (TMS320C55_INS_AADD, TMS320C55_INS_B, TMS320C55_INS_CALL, ...) covering
  C55x and C55x+, plus tms320c55x_insn_name(), tms320c55x_insn_id_from_syntax()
  and tms320c55x_insn_optype(). The prefix is TMS320C55_ / tms320c55x_
  rather than TMS320_ / tms320_ because the other TMS320 families (C54x,
  C64x, C28x) have substantially different instruction sets; the enum,
  the file and these helpers are C55x/C55x+ specific.

* insn_head_t gains an .id field; every head entry in c55x/table.h is
  tagged with its TMS320C55InsID. The disassembler resolves the decoded
  instruction ID from the emitted mnemonic (so multi-form leading bytes
  such as 0x95 -> intr/trap, 0x48 -> ret/reti/rpt, 0x50 -> sftl/popboth
  resolve to the exact instruction, which a static byte->head map cannot).
  tms320_dasm_t gains an insn_id field and tms320_dasm_insn_id() accessor.

* tms320_c55x_insn_id_decode() / tms320_c55x_plus_insn_id_decode() let the
  analyzers resolve the named ID for a byte sequence via a cached decoder
  instance.

* The C55x analyzer's dispatch is rewritten from switch(opcode_byte) to
  switch(TMS320C55InsID). Both analyzers set op->id to the named ID, the
  same way the Capstone-based plugins (e.g. c64x) populate op->id.

* The C55x+ analyzer keeps its byte-level dispatch for control flow,
  stack deltas and operands, but takes the final arithmetic/logical/move/
  multiply/stack type from tms320c55x_insn_optype(op->id). A leading byte on
  C55x+ encodes several instructions (selected by operand bits), so the
  byte switch alone cannot tell ADD from SUB, AND from OR/XOR, or AMOV
  from ASUB; the decoded id can.

Bugs fixed
==========

Driving dispatch / typing from the decoded id fixes a number of latent
mis-classifications the raw-byte switch had masked, verified against the
TI dis55 reference disassembler and the C55x+ documentation:

  - 0x50 0x66 (psh Tx) was typed SHL; now a stack push (corrects
    sym._main's computed stackframe in the rel.stripped.coff test).
  - 0x48 0x05 (reti) was typed REP; now RET.
  - 0x95 0x0F / 0x8F (intr vs trap) distinguished by the decoder.
  - C55x+ 0x7B: byte1 bit7 selects LD (mov) vs add/sub, and within
    add/sub byte2 bit7 selects sub; was always typed add/mov by nibble.
    (TI SWPU104 Table 7-2, opcode 01111011.)
  - C55x+ 0xD2 mar(XDAa op k24): address-register modify, now LEA like
    AADD / AMOV; was typed SUB. (Table 7-2, opcode 11010010.)
  - 57 further C55x+ arith/logical/move/stack contradictions found by
    cross-referencing a Motorola Droid (Wrigley3G) C55x+ baseband dump
    against the decoder are resolved by the optype override.

* DELAY is a memory-delay MOVE per TI SWPU104 sec.6.7.1 (Memory Delay,
  grouped under Move Operations): it copies Smem to Smem+1. Both
  analyzers now mark it as a memory access (width 2, write) and drop the
  spurious FAMILY_CPU (CPU is already the default family).

Tests
=====

New checks assert op->id carries the right TMS320C55_INS_* value on each
CPU, plus regression tests for every byte/decoded-id mismatch fixed above
(c55x: 0x50/0x48/0x95/0xb6; c55x+: 0x7b/0xd2). The c55x opcode-
classification and stackframe expectations are updated to the corrected
output.

Cross-reference
===============

  TI SPRU374    'TMS320C55x DSP Mnemonic Instruction Set Reference Guide'
  TI SWPU086    'TMS320C55x+ DSP Algebraic Instruction Set Reference Guide'
  TI SWPU104    'TMS320C55x+ DSP Mnemonic Instruction Set Reference Guide'
2026-05-28 17:44:54 +08:00
Anton Kochkov
6d57743bb6 arch/tms320: add README explaining the three supported CPUs
Short summary of the three cpu= values supported by the tms320 arch
plugin (c55x, c55x+, c64x), the silicon they map to, and a note on
the two distinct meanings of 'c55x+': TI's publicly-named C55x DSP
Core+ shipping in current low-power C55x parts (C5504-C5545), and
the pre-release Ryujin revision documented in TI SWPU086 / SWPU104
that lives in older modem silicon. The rizin plugin handles both.
2026-05-28 17:44:54 +08:00
Anton Kochkov
d81489e40d bin/dwarf: force big-endian read on TMS320 COFF DWARF sections
TI's cl55 compiler writes COFF files with little-endian file and
section headers, but the data inside DWARF sections (.debug_info,
.debug_abbrev, .debug_frame, .debug_line) is laid out as 16-bit
big-endian words. The DWARF parser was reading the unit length as
LE and getting absurd values, then bailing out with zero
compilation units.

Result: afvl, avgl, afs all returned empty for every
emulateme*.ticoff2.dbg.coff in rizin-testbins even though the
file had a fully-populated .debug_info section, the abbrev
tables parsed cleanly, and the per-architecture DWARF register
mapping (added separately) was available.

Override bf_bigendian() for arch=tms320 so the DWARF endian reader
swaps correctly. The COFF info struct stays in the same
little-endian state it always was; only the dwarf reader's view
flips.

After this fix, cl55-compiled TI COFF v2 binaries with debug info
yield:
  afvl @ dbg.main  -> arg int argc @ ar4
  afs  @ dbg.main  -> int main(int argc);
  avgl             -> 7 globals (uart_address, seckrit, _lock, ...)
  pdf  @ <fn>      -> renders with signatures, named args, reflines,
                      resolved call targets
2026-05-28 17:44:54 +08:00
Anton Kochkov
4221d56cb9 arch/tms320: c55x and c55x+ analysis classifiers (byte-driven)
Rewrites the C55x and C55x+ analysis classifiers as pure byte-level
dispatch -- no mnemonic-string matching, no round-trip through the
disassembler -- and adds the supporting infrastructure they need to
produce useful RzAnalysisOp metadata.

What lands
==========

* librz/arch/isa/tms320/c55x/c55x_analysis.{c,h} -- C55x baseline
  classifier, ~360 lines, 256-entry size table extracted from the
  decoder's table.h.
* librz/arch/isa/tms320/c55x_plus/c55plus_analysis.c -- C55x+
  classifier rewritten in the same shape, ~470 lines covering 90+
  opcodes with byte-level disambiguation for 0x02 / 0x03 / 0x74 /
  0x76 / 0x7B / 0xC5.
* librz/arch/isa/tms320/tms320_dwarf_regnum_table.h plus a hook in
  librz/arch/dwarf_process.c -- TI cgt55 ABI DWARF register-number
  mapping, so the cl55 compiler's .debug_info variable locations
  resolve into rizin register names instead of returning the dummy
  "?" placeholder.
* librz/arch/p/analysis/analysis_tms320.c -- thin dispatcher that
  picks the per-cpu classifier and stops carrying the tms320_dasm_t
  engine in analysis state.

Why a byte-driven classifier
============================

The old classifier round-tripped through the disassembler and did
strncasecmp() on the mnemonic string. Three problems:

1. It kept a tms320_dasm_t engine alive in the analysis context
   just to read its 'syntax' buffer after every classify call.
   Removing it shrinks the per-analysis state and removes a
   tms320_dasm_init/_fini pair from the analysis_init/_fini path.

2. It only set op->type -- never op->jump, op->fail, op->stackop,
   op->stackptr, op->val, op->eob. Basic-block formation followed
   only the most obvious control flow, and call/ret/push/pop
   semantics were invisible to higher-level analysis.

3. It couldn't disambiguate predicated versus unconditional calls:
   the disassembler emits 'callcc' vs 'call', but the substring
   match missed the conditional fail-path for CALLCC.

The new classifiers fix all three:

  - Read the leading byte (and second-byte refinements where the
    encoding family is shared) directly from buf.
  - Resolve jump and call targets from BE-stored displacement and
    absolute fields, with correct sign extension for the 8-bit and
    16-bit relative forms.
  - Read 24-bit absolute targets via rz_read_at_be24().
  - Set op->fail = addr + size for every conditional jump/call,
    op->eob = true for unconditional branches and RET so basic-block
    walkers terminate correctly.
  - Track the stack: PSH/POP per ISA cluster, CALL/CALLCC +2,
    RET/RETI -2.
  - Capture INTR/TRAP immediates in op->val via set_imm().
  - Disambiguate sub-opcodes that share a leading byte by reading
    the relevant bits of the second byte. For C55x, the most
    notable case is 0x48 (RPT/RPTADD/RPTSUB/RET/RETI) which uses
    bits 0-2 of byte 1; for C55x+ the disambiguations are 0x02,
    0x03, 0x74, 0x76, 0x7B and 0xC5.
  - Handle parallel-prefix bytes (odd-valued leading bytes below
    0x80 in C55x like 0x03, 0x05, 0x07, 0x11, ...) by treating
    them as a 1-byte prefix and dispatching on byte 1 so paired
    '|| retcc', '|| bcc', etc. classify correctly.

Both classifiers ship analyzer helpers (set_cjmp, set_call, set_jmp,
set_ret, set_cret, set_push, set_pop, set_imm, set_mem_width,
set_dst_reg, set_ireg, set_dir, set_disp) so each opcode entry fills
the RzAnalysisOp ptr / val / stackop / stackptr / fail / eob fields
uniformly across both architectures.

DWARF register mapping
======================

Loading any cl55-compiled TI COFF v2 with debug info (every
emulateme*.ticoff2.dbg.coff in rizin-testbins) used to fire:

  ERROR: No DWARF register mapping function defined for tms320 32 bits

per variable, because dwarf_process.c had no entry for arch=tms320.
The new tms320_dwarf_regnum_table.h covers the cgt55 ABI numbering:
AC0-AC3, T0-T3, AR0-AR7, SP/SSP/CDP, BK03/BK47/BKC, DP/PDP, CSR,
BRC0/BRC1, TRN0/TRN1, RPTC, IER0/IER1, IFR0/IFR1, DBIER0/DBIER1,
IVPD/IVPH, ST0_55..ST3_55 (42 entries). Reach into the table is
guarded; out-of-range numbers fall back to NULL so the caller
surfaces the dummy "?" instead of confidently picking the wrong
register.

Wrigley3G coverage
==================

Validation against a 3.1 MB Wrigley3G baseband firmware (Motorola
Droid A855, MSG39UPEU_A1.19_1.80, partition CG45.img) found 31
leading-byte values producing real instructions classified as NULL.
The c55x+ classifier here covers those:

  0x50-0x5F        MOV memory/register cluster
  0x88, 0x8A       MOV ACx <-> mem high/low halves
  0x8C             ADD with carry, mem -> ACx
  0x97             Dual-memory MOV (parallel)
  0xA0             MOV with parallel dual addressing
  0xAC, 0xAD       MOV #k16, ACx (long immediate)
  0xB4, 0xB5       MOV with rounding and shift
  0xB6, 0xB7       ADD with shift (T-register or immediate)
  0xC0, 0xC2, 0xC4 ADD #k16 with shift slots
  0xCC             Packed ADD :: MOV dual-instruction encoding
  0xD0             MOV ACx, dbl(*(#abs24))
  0x2E, 0x2F       XCCPART predicated execute
  0x0B, 0x23       Wrigley silicon pseudo-ops (TRAP)
  0xC6             BFXTR / BFXPA bit-field extract (MOV)

The 0x03 family classifier extends from a 4-bit (0xF0) to a 6-bit
(0xC0) mask so the full encoded range resolves:

  0x03 0x00-0x3F   INTR #k5
  0x03 0x40-0x7F   TRAP #k5
  0x03 0x80-0xBF   SWAP register pairs
  0x03 0xC0-0xFF   SIM_TRIG (Wrigley-specific simulator trigger)

Coverage on Wrigley3G rises from 94.4% to 97.4% (2000-sample
random survey).

Tests
=====

Two new test suites land alongside the classifiers:

  test/db/analysis/tms320.c55x_32       11 tests (batched)
  test/db/analysis/tms320.c55x+_32      13 tests (batched + binary
                                                  fixtures)

Tests are intentionally batched -- each test bundles 10-12 opcode
checks behind one rizin process spawn instead of one per check.
That brings both suites down to under 0.5 seconds combined.

The c55x+ suite includes six binary-fixture tests against the
companion rizin-testbins drop-in tms320/coff2/*.obj corpus,
covering function discovery (afl), stack-pointer tracking
(afvs / afS), data-section walk (iS), and globals enumeration
(is). The c55x suite covers tms320/emulateme_nostd.ccsv5.c55x
.ticoff2.dbg.coff from the existing rizin-testbins tree.

Cross-reference
===============

  TI SPRU374    'TMS320C55x DSP Mnemonic Instruction Set Reference
                Guide' (publicly available) -- C55x baseline.
  TI SWPU086    'TMS320C55x+ DSP Algebraic Instruction Set Reference
                Guide' (May 2005) -- C55x+ instruction encodings.
  TI SWPU104    'TMS320C55x+ DSP Mnemonic Instruction Set Reference
                Guide' (December 2006) -- C55x+ mnemonic forms.
2026-05-28 17:44:54 +08:00
Anton Kochkov
e0ce234a35 arch/tms320/c55x_plus: decode V/VV field as Carry/TC2 and expand asm corpus
Two related fixes to the c55x+ disassembler glue, plus the matching
expansion of the c55x+ asm test corpus from 25 to 104 cases.

V/VV decode (case 51)
2026-05-28 17:44:54 +08:00
Anton Kochkov
385daedf70 arch/tms320/c55x_plus: modernize disassembler glue
The c55x_plus disassembler glue layer (c55plus.c) is rewritten as a
thin shim over the th0rpe c55plus_decode() walker:

  - Drop the ad-hoc ctype tolower() loop; use rz_str_case() to
    lower-case the walker's mixed-case mnemonics in one call.
  - Reorder the includes; drop the unused ones.
  - Scope local variables to where they are actually used.
  - Move the global setup (ins_buff / ins_buff_len) into the same
    block as the c55plus_decode() call so the dataflow is obvious.

While here, fix a pre-existing off-by-one in utils.c. The hex-digit
lookup table was declared as a 17-character string with a duplicated
leading '0':

  static char hex_str[] = "01234567890abcdef";

This shifted every nibble >= 0xA by one position in the table:

  hex_str[10] = '0'  (should be 'a')
  hex_str[11] = 'a'  (should be 'b')
  ...
  hex_str[15] = 'e'  (should be 'f')
  hex_str[16] = 'f'  (unreachable)

Result: get_hex_str(0xff) returned "ee", get_hex_str(0xab) returned
"0a", and every disassembled '.byte 0xNN' for an unknown opcode with
nibbles >= A came out wrong. The function is used from
c55plus_decode.c on the unknown-opcode fallback path
(hash_code == 0x223), so the bug surfaces whenever the decoder bails
out and emits a raw byte.

Fix: use the correct 16-character table "0123456789abcdef" and rename
the static to hex_digits to make the role obvious. While here, tidy
strcat_dup() to use bitwise tests on the n_free bitmask so the
'3 = free both' contract is enforced uniformly, add docstrings to both
helpers, and drop the redundant memcpy length guard that was a no-op
for non-NULL length-zero strings.

No behavioural change for either piece beyond the bug fix above.
2026-05-28 17:44:54 +08:00
Anton Kochkov
9ccee37999 arch/tms320/c55x_plus: drop utils.{c,h}, use rz_util helpers
The c55x_plus decoder shipped with two private string helpers in
utils.c:

  strcat_dup(s1, s2, n_free)  - allocate s1+s2 and optionally free
                                inputs, with a bitmask controlling
                                which of s1/s2 are released
  get_hex_str(n)              - format the low 8 bits of n as a
                                two-character lowercase hex string

Both have direct equivalents in rz_util:

  strcat_dup(s, lit, 1)       -> rz_str_append(s, lit)
  strcat_dup(lit, s, 2)       -> rz_str_prepend(s, lit)
  strcat_dup(s1, s2, 3)       -> rz_str_append_owned(s1, s2)
  strcat_dup(s1, s2, 1) where
    s2 is also owned and freed
    manually right afterwards -> rz_str_append_owned(s1, s2)
  get_hex_str(n)              -> rz_str_newf("%02x", n & 0xff)

This commit converts all 56 strcat_dup call sites in
c55plus_decode.c and decode_funcs.c plus the single get_hex_str
site, then deletes utils.c and utils.h entirely.

While here, replace several local sprintf-into-stack-buffer +
rz_str_dup patterns with direct rz_str_newf calls:

  - get_AR_regs_class1: was malloc(50) + sprintf per case, now a
    single rz_str_newf per case returning the result directly.
    The function is reduced from 34 lines to 14.
  - get_AR_regs_class2: same pattern, reduced from 130 lines to
    79 with no allocation needed at the top.
  - get_token_decoded case 40/48, 70/72/80, 41/73: sprintf into
    a 512-byte stack buffer then rz_str_dup -> single rz_str_newf.
  - decode_funcs.c case 2 of get_status_regs_and_bits: was
    calloc(50) + sprintf, now rz_str_newf.

The 512-byte stack buffer 'buff_aux' in get_token_decoded becomes
unused and is removed.

C55PLUS_DEBUG, the only useful symbol that used to live in utils.h,
moves to ins.h (which all c55x_plus translation units transitively
include). ins.h gains a direct <rz_util.h> include so the rest of
the headers don't need to pull it in indirectly.

No behavioural change. Full c55x_plus test regression passes:
asm/tms320_c55x+_32 104/104, analysis/tms320.c55x+_32 45/45,
parity against TI dis55.exe v4.3.6 on the 13-source testbins corpus
remains 140/140.
2026-05-28 17:44:54 +08:00
Anton Kochkov
64c1cad7e5 bin/coff: promote globals in code sections to FUNC
COFF C_EXT (external/global) symbols carry their function-or-not
status in two places: the DTYPE field of n_type (the ISFCN bit), and
implicitly by the section they live in. The existing code only
honoured the DTYPE bit:

  ptr->type = DTYPE_IS_FUNCTION(s->n_type) || !strcmp(name, "main")
      ? RZ_BIN_TYPE_FUNC_STR : RZ_BIN_TYPE_UNKNOWN_STR;

C and C++ compilers set the ISFCN bit when emitting object code, so
this works for compiled output. But assembler-emitted globals -- TI's
asm55p / cl55, the GNU GAS COFF backend on legacy targets, and any
hand-written .s -- often leave n_type at zero. Every assembly symbol
then comes back as RZ_BIN_TYPE_UNKNOWN_STR, and 'aaa' has no way to
distinguish a function from a data label. Concrete example: with TI
asm55p output for the C55x+ test corpus, none of the eight .global
labels in 03_branches_calls.s (_short_ret, _short_branch, _short_call,
...) were promoted to functions, so analysis only found those
reachable by following control flow from a hard-coded entry.

Add a section-flag fallback: if the symbol's containing section has
COFF_SCN_CNT_CODE set (i.e. it's a .text / code section), the symbol
is a function. This keeps the DTYPE check as the primary signal but
fills the gap on assembler output.

Verified with TI C55x+ .obj files: all .global labels now appear as
RZ_BIN_TYPE_FUNC_STR and are picked up by 'aaa'. No regression on
the standard COFF test suite (Windows i386/amd64 .obj from compiled
C output).
2026-05-28 17:44:54 +08:00
Anton Kochkov
88a4121d70 bin/coff: support TI COFF v2 48-byte section header
The COFF section table walker assumed every COFF section header is
40 bytes -- the standard COFF1 form. The TI Common Object File Format
(SPRAAO8) extends this for TI COFF v2 (file magic 0x00C2) used by the
TI tools (asm55, cl55, cl6x, cl28, etc.):

  ------------------------------------------------------------------
  offset  size  field         standard COFF1     TI COFF v2
  ------------------------------------------------------------------
  0x00    8     s_name        char[8]            char[8]
  0x08    4     s_paddr       ut32               ut32
  0x0c    4     s_vaddr       ut32               ut32
  0x10    4     s_size        ut32               ut32
  0x14    4     s_scnptr      ut32               ut32
  0x18    4     s_relptr      ut32               ut32
  0x1c    4     s_lnnoptr     ut32               ut32
  0x20    2/4   s_nreloc      ut16               ut32  <-- widened
  0x22    2/4   s_nlnno       ut16               ut32  <-- widened
  0x24    4     s_flags       ut32               ut32
  0x28    -     reserved      -                  ut16  <-- new
  0x2a    -     mempage       -                  ut16  <-- new
  ------------------------------------------------------------------
  TOTAL          40                              48

Reading TI COFF v2 with the standard 40-byte stride walks the section
table off-by-8 per section, producing nonsense values for every
section after the first. In practice, vaddr and size for the second
section spill into the next section's name field, surfacing as
attention-grabbing decimal values like 0x7461642e (ASCII '.dat'
reversed -- bytes from the upcoming '.data' name being interpreted as
a size).

Concrete reproducer with TI asm55p output:
  $ wine asm55p.exe -v5505 03_branches_calls.s
  $ rz-bin -S 03_branches_calls.obj                # before this fix
  ...
  0x00000061 0x7461642e 0x00000040 0x7461642e ...  # garbage size
  ...
  $ rz-bin -S 03_branches_calls.obj                # after this fix
  0x000000fa       0x34 0x00000030       0x34 -r-x .text
  ...

Fix: add a parallel coff_init_scn_hdr_ti() that reads the 48-byte
layout, with nreloc/nlnno as ut32 (clamped to ut16 because the rest
of the COFF code keeps them as 16-bit and counts above 64K are not
encountered in practice). bin_coff_init_scn_hdr() picks the variant
based on coff_is_ti_machine() -- the same predicate already used in
the file-header parser to consume TI's f_target_id field.

Tested with TI asm55p output for C55x, C55x+, and C5500 (machine ids
0x9c, 0xa1, and TI_1/TI_2 file magics) -- sections now parse with the
correct sizes, vaddrs, and flags, and the resulting binaries open
cleanly under 'rizin -A' for analysis.
2026-05-28 17:44:54 +08:00
Anton Kochkov
d2c67fe2c5 arch/tms320: fix =PC alias in c64x register profile
The c64x branch of tms320_reg_profile() declared '=PC pc' but only
ever registered pce1 -- pc was never one of c64x's declared registers.
This raised:

  WARNING: Invalid alias given in register profile: pc.

on every rz-asm / rizin invocation of any tms320 cpu, including c55x
and c55x+, because the warning fires during analysis init before the
cpu-specific branch of the profile is selected.

The C64x ISA uses pce1 (Program Counter Extension 1, .32 at index
545) as its program counter -- the only PC-named control register
declared in the c64x profile -- so '=PC pce1' is the correct alias.
The companion test/db/analysis/tms320.c64x_32 'arp' expectation is
updated to match.

The c55x / c55x+ branch (is_c5000) is unchanged -- those profiles do
declare 'pc' as a 24-bit program counter, so '=PC pc' stays valid
there.

This change is independent of the c55x_plus work in the rest of this
series; it would be a useful cleanup on its own. Included here because
it surfaces immediately whenever any of the new c55x+ analysis tests
are run.
2026-05-28 17:44:54 +08:00
Florian Märkl
7e97635726
Avoid overlapping memcpy in rz_vector_sort() (#6411)
Detected with valgrind, some element assignments could memcpy with
identical addresses. This is usually a no-op in practice, but
theoretically undefined behavior.
2026-05-28 06:33:45 +02:00
NOT XVilka
9960ae3bed
test/bench: add benchmark for RzDiff (#6398)
Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
2026-05-27 18:36:58 +08:00
Khairul Azhar Kasmiran
1abe2dce99
Prevent RzBuffer's Oxff_priv from overriding io.0xff (#6371)
* Prevent RzBuffer's `Oxff_priv` from overriding `io.0xff`
* Use io from RZ_BUFFER_IO and RZ_BUFFER_IO_FD buffers
* Add `RzIO *` param to rz_buf_new_mmap()
* pe: Discard incomplete import directory
2026-05-27 06:18:45 +08:00
Rot127
c6820479c6
test/bench: add geometric stats to benchmarks (#6403)
* Add option to replace (geometric) invalid values with another value.
* Add geometric Mean and Std Dev to benchmarks.
* Add Doxygen documentation
* Add a README to the bench dir as intro.
2026-05-26 16:15:02 +08:00
Florian Märkl
0b74a61fe4
Install missing rz_math.h header (#6401)
Added in 702250eb4f but not installed
2026-05-25 10:32:36 +02:00
Florian Märkl
a72a275ca2
Fix deadlock in rz_th_queue_close_when_empty() (#6383)
empty_cond was never signalled and the termination depended only on
the timeout in rz_th_queue_close_when_empty() causing a re-check of
emptiness.
However, the rz_th_cond_timed_wait() implementation, which was used
there, was flawed because it expected a relative timeout but passed that
directly to pthread_cond_timedwait() which expected an absolute time
value, practically causing it to time out immediately. Depending on the
pthread_cond implementation, this possibly created a situation where the
mutex could never be acquired by another thread, effectively causing a
deadlock. This behavior was observed on Mac OS X 10.5 (ppc) when running
the test_core_bin test.
We solve this by not using a timeout at all and signalling the condition
variable for all waiting threads at the appropriate time.
2026-05-25 09:25:29 +02:00
Rot127
702250eb4f
test/bench: measure standard deviation for benchmarks (#6390)
* Add Welfords square of sums algorithm for variance and std deviation calculations.
* Add standard deviation to benchmarks
* Simplify Welford
* Add geometric mean and standard deviation to Welford Sums
2026-05-25 05:08:06 +08:00
bubblepipe
6be10c2428
librz/core/analysis: fix data xref in K64F-RIOT-SPI.elf not marked properly (#6363) 2026-05-25 00:15:39 +08:00
MrQuantum1915
a54489190b
librz/core: implement ROP/JOP/COP gadget cache (#6328) 2026-05-24 21:48:42 +08:00
Khairul Azhar Kasmiran
60f39e2df5
librz/bin/pe: discard incomplete section headers (#6397)
* PE: discard incomplete section headers
* Invert logic
2026-05-24 01:11:43 +08:00
Rot127
12a16c812b
Add order ignoring remove_at version with better performance. (#6389)
* Add order ignoring remove_at version with better performance.

* Optimize rz_vector_swap by using stack memory for small elements.

* Add benchmark for rz_vector_swap
2026-05-22 20:54:49 +00:00
Rot127
75cd389b5c
Graph - API changes to enum (#6349)
* Refactor del_edges to use RzGraphStatus.

* Refactor del_edge() to use RzGraphStatus.

* Refactor update_edge() to use RzGraphStatus.

* Refactor has_edge() to use RzGraphStatus.

* Refactor add_edge() to use RzGraphStatus.

* Fix leak of b

* Fix leak of xref list

* Fix leaks of analysis ops

* Address review comments

* Inlcude clean up

* Fix invalid free

* Add tests with node and edge data.

* Extend tests
2026-05-22 13:45:18 +00:00
Florian Märkl
3526b09423
Fix unit tests on 32-bit platforms (#6384)
Various issues related to pointer size and RzVector behavior.
Testing rz_pvector_shrink() at the place removed here is not necessary
as it has its own dedicated tests.
2026-05-19 11:44:32 +08:00
Florian Märkl
65313b186c
Add rz_analysis_get_cpu() API and use it in plugins (#6353)
Now that the RzAnalysis struct is private, it is necessary to have this
API for plugins outside the rizin codebase.
2026-05-19 02:33:12 +08:00
Rot127
8a76ab1733
Bump demangler to latest commit + fix useless code (#6381)
* Update libdemangle to fix reachable double free
* Get some return on an energy burning loop.
2026-05-18 23:20:19 +08:00
SSharshunov
b2297073bf
librz/bin/omf166: fix format errors and if_fail macroses (PFMTSZu) (#6368) 2026-05-17 20:21:05 +08:00
MrQuantum1915
d25f2be0d2
shell/rop: highlight conditional gadgets in all modes (#6324) 2026-05-17 03:41:17 +08:00
MrQuantum1915
258b5ed989
Arange fields in descending order of size (#6360) 2026-05-16 23:12:58 +08:00
Giovanni
5e7fa12b5a
Add RzConfigValidator for validating (on set) owned variables (#6356) 2026-05-16 16:12:13 +02:00
SSharshunov
ee3e628c8a
librz/bin/omf166: fix format errors and if_fail macroses (#6362) 2026-05-16 21:06:31 +08:00
Rot127
1adba3227a
librz/util/graph: various improvements
* GRAPH: Add rz_graph_add_get_node() and refine API.
* GRAPH: Remove unused, and rename parameters.
* Improve doxygen.
* Implement rz_graph_del_edges()
* Rename rz_graph_node_get_hash_id() to rz_graph_node_get_hash_id() to make clear what identifier is returned.
* Simplify node identification.

Removes the option to have two sources of identifiers (node data or other identifier data).
Changes the API to use the hash id instead of a pointer to data.

* Fix type annotations.
* Remove duplicate function.
* Fix invalid asserts.
* Set flag if node was present.
* Grow by a factor of 1.25. Exponential growth quickly leads to OOM.
* Remove the edge index again to not remove reduce the main advantage of an adjacency matrix
* Refactor list based graph to use vectors instead of hash maps for edges.
* Fix heap-use-after-free
* Add an rz_graph_update_edge function.
* Add function to print graph as dot graph.
* Add warning about del_edges runtime.
* Refactor add_node to use RzGraphStatus.
* Refactor del_node to use RzGraphStatus.
* Use cast-macro to prevent ASAN issues.
2026-05-16 19:12:01 +08:00
Khairul Azhar Kasmiran
c969056558
Fix bb refcount when bb is overlength (#6358) 2026-05-16 13:02:26 +08:00
SSharshunov
5256726d00
librz/arch/c166: remove unnecessary use of assert macroses (#6345) 2026-05-15 23:53:27 +08:00
MrQuantum1915
e8708c62d5
librz/arch/arm: fix memory leaks of RzILOpBitVector (#6354) 2026-05-15 23:37:34 +08:00
Khairul Azhar Kasmiran
17fd3815c6
Use -1 with tiny test (#6352) 2026-05-15 18:00:11 +08:00
SSharshunov
e4976144c3
librz/bin/omf166: fix coverity issues (#6346)
* CID 909878
* CID 909868
* CID 909875
* CID 909860
2026-05-15 01:52:20 +08:00
Giovanni
b56a44d9f0
test/unit: remove WITH_GPL from DWARF C++ test (#6351) 2026-05-14 23:36:29 +08:00
well-mannered-goat
5dd20c43b5
librz/bin/elf: improve aarch64 relocs support (#6022) 2026-05-14 12:54:12 +08:00
Arya H R
9ce185e507
librz/arch/luajit: fix parsing on big-endian machines (#6350) 2026-05-14 12:53:19 +08:00
Giovanni
2d1cff75ee
librz/bin/elf: add some missing MIPS relocs (#6348)
* Add support to various MIPS reloc conversion.

R_MIPS_26, R_MIPS_HI16, R_MIPS_LO16, R_MIPS_GOT16, R_MIPS_PC16,
R_MIPS_CALL16, R_MIPS_64, R_MIPS_GOT_HI16, R_MIPS_GOT_LO16,
R_MIPS_CALL_HI16, R_MIPS_CALL_LO16, R_MIPS_REL16

* Fix test missing RUN at the end.
2026-05-14 00:52:59 +08:00
Khairul Azhar Kasmiran
263a4b1b49
Fix afb-* (#6347)
* Base test output
* Fix `afb-*`
2026-05-14 00:52:20 +08:00
SSharshunov
75ad6e9a51
librz/arch/c166: fix behavior on big-endian hosts 2026-05-13 04:28:29 +08:00
NOT XVilka
93eeefc399
librz/core: fix OMF debug type error (#6343)
Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
2026-05-13 02:54:02 +08:00
NOT XVilka
9db62b03fa
librz/bin/omf: OMF166 fix error handling (#6342)
Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
2026-05-13 00:47:50 +08:00
Rot127
1750cc27fc
librz/bin/omf: fix build warning (#6341) 2026-05-13 00:47:23 +08:00