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.
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
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.
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'
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.
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
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.
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.
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.
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).
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.
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.
Detected with valgrind, some element assignments could memcpy with
identical addresses. This is usually a no-op in practice, but
theoretically undefined behavior.
* 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.
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.
* 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
* 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
* 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
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.
* 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.
* 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.